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 = "\nCopyright (C) 1993--2000 Y&Y, Inc.\n"
97 "Copyright (C) 2007 TeX Users Group.\n"
98 "Copyright (C) 2014 Clerk Ma.\n\n"
99 "This program is free software; you can redistribute it and/or modify\n"
100 "it under the terms of the GNU General Public License as published by\n"
101 "the Free Software Foundation; either version 2 of the License, or\n"
102 "(at your option) any later version.\n\n ";
103 char *yandyversion = "2.2.3";
104 char *application = "Y&Y TeX"; /* 96/Jan/17 */
105 char *tex_version = "This is TeX, Version 3.14159265";
107 /* #define COPYHASH 1890382 */
108 /* #define COPYHASH 13862905 */
109 /* #define COPYHASH 10558802 */
110 /* #define COPYHASH 7254699 */
111 /* #define COPYHASH 3950596 */
112 /* #define COPYHASH 646493 */
113 #define COPYHASH 12905299
115 clock_t start_time, main_time, finish_time;
117 char * dvi_directory = ""; /* user specified directory for dvi file */
118 char * log_directory = ""; /* user specified directory for log file */
119 char * aux_directory = ""; /* user specified directory for aux file */
120 char * fmt_directory = ""; /* user specified directory for fmt file */
121 char * pdf_directory = ""; /* user specified directory for pdf file */
123 char * texpath = ""; /* path to executable - used if env vars not set */
125 // #define MAXLINE 256
127 char log_line[MAXLINE]; // used also in tex9.c
129 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
130 int format_spec = 0; /* non-zero if a format specified on command line */
131 int closed_already = 0; /* make sure we don't try this more than once */
132 bool reorder_arg_flag = true; /* put command line flags/arguments first */
134 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
135 /* Used in tex0.c with wintodos[c-128] */
137 unsigned char wintodos[128] = {
138 0, 0, 0, 159, 0, 0, 0, 0,
139 94, 0, 0, 0, 0, 0, 0, 0,
140 0, 96, 39, 0, 0, 7, 0, 0,
141 126, 0, 0, 0, 0, 0, 0, 0,
142 32, 173, 189, 156, 207, 190, 221, 21,
143 0, 184, 166, 174, 170, 45, 169, 0,
144 248, 241, 253, 252, 0, 230, 20, 250,
145 0, 251, 167, 175, 172, 171, 243, 168,
146 183, 181, 182, 199, 142, 143, 146, 128,
147 212, 144, 210, 211, 222, 214, 215, 216,
148 209, 165, 227, 224, 226, 229, 153, 158,
149 157, 235, 233, 234, 154, 237, 232, 225,
150 133, 160, 131, 198, 132, 134, 145, 135,
151 138, 130, 136, 137, 141, 161, 140, 139,
152 208, 164, 149, 162, 147, 228, 148, 246,
153 155, 151, 163, 150, 129, 236, 231, 152
156 void show_usage (char * program)
160 " yandytex [-?ivnwdrzpK] [-m=ini_mem] [-e=hyph_size] [-h=trie_size]\n"
161 " [-x=xchr_file] [-k=key_file] [-o=dvi_dir] [-l=log_dir] [-a=aux_dir]\n"
162 " [+format_file] [tex_file]\n\n"
163 " -? show this usage summary\n"
164 " -i start up as iniTeX (create format file)\n"
165 " -v be verbose (show implementation version number)\n"
166 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
167 " -w do not show `non ASCII' characters in hexadecimal (show as is)\n"
168 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
169 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
170 " -p allow use of \\patterns after loading format (iniTeX only)\n"
171 " -K disable all extensions to basic TeX\n"
172 " -m initial main memory size in kilo words (iniTeX only)\n"
173 " -e hyphenation exception dictionary size (iniTeX only)\n"
174 " -h hyphenation pattern trie size (iniTeX only)\n"
175 " -x use `non ASCII' character mapping (xchr[]) defined in file\n"
176 " -k use `key replacement' defined in file\n"
177 " -o write DVI file in specified directory (default current directory)\n"
178 " -l write LOG file in specified directory (default current directory)\n"
179 " -a write AUX file in specified directory (default current directory)");
181 show_line(log_line, 1);
183 uexit(1); // has this been setup yet ???
187 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
189 /* -c prepend current directory (.) to TFM directory list\n\ */
190 /* -b check that files with read access are not actually directories\n\ */
192 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
193 /* \t\t(applies to file name and format file name, if present)\n\ */
194 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
196 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
198 /* Sep 27 1990 => 1990 Sep 27 */
199 /* 012456789 0123456789 */
201 void scivilize (char * date)
205 strcpy (pyear, date + 7);
206 for (k = 5; k >= 0; k--) date[k + 5] = date[k];
207 for (k = 0; k < 4; k++) date[k] = pyear[k];
209 if (date[9] == ' ') date[9] = '0'; /* replace space by '0' */
213 /* Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35 */
215 void lcivilize (char * date)
220 strcpy (pyear, date + 20);
221 for (k = 18; k >= 0; k--) date[k+1] = date[k];
222 /* date[20] = '\n'; */
223 /* date[21] = '\0'; */
225 for (k = 0; k < 4; k++) date[k] = pyear[k];
230 // void stamp_it (FILE *outfile)
231 // now writes result into given buffer
232 void stamp_it (char *s)
236 strcpy(date, compiledate);
238 sprintf(s, "%s %s ", application, yandyversion);
240 sprintf(s, "(compiled time: %s %s)", date, compiletime);
244 void stampcopy (char *s)
248 sprintf(s, "%s %s", copyright, www); /* 99/Oct/25 */
252 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
257 void read_xchr_sub (FILE * xchr_input)
259 char buffer[PATH_MAX];
260 int k, from, to, count = 0;
264 memset (xchr, NOTDEF, MAXCHRS); /* mark unused */
266 for (k = 0; k < MAXCHRS; k++) xchr[k]= -1; /* mark unused */
269 memset (xord, NOTDEF, MAXCHRS); /* mark unused */
271 for (k = 0; k < MAXCHRS; k++) xord[k]= -1; /* mark unused */
274 #ifdef ALLOCATEBUFFER
275 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
277 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
280 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
281 /* if (sscanf (buffer, "%d %d", &from, &to) < 2)
282 sprintf(log_line, "Do not understand: %s", buffer); */
283 from = (int) strtol (buffer, &s, 0);
284 to = (int) strtol (s, NULL, 0);
285 /* what if line is bad ? do we just get from = 0 and to = 0 ? */
286 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS) {
287 if (xchr[from]== (unsigned char) NOTDEF)
288 xchr[from]= (unsigned char) to;
290 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
291 show_line(log_line, 0);
293 if (xord[to]== NOTDEF)
294 xord[to]= (unsigned char) from;
296 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
297 show_line(log_line, 0);
302 /* now fill in the gaps */ /* not clear this is a good idea ... */
303 for (k = 0; k < MAXCHRS; k++) {
304 if (xchr[k]== NOTDEF) { /* if it has not been filled */
305 if (xord[k]== NOTDEF) { /* see whether used already */
306 xchr[k]= (unsigned char) k; /* no, so make identity */
307 xord[k]= (unsigned char) k; /* no, so make identity */
311 xchr[NOTDEF]= NOTDEF; /* fixed point of mapping */
313 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
314 show_line(log_line, 0);
315 for (k = 0; k < MAXCHRS; k++) {
316 if (xchr[k]!= NOTDEF) {
317 sprintf(log_line, "%d => %d\n", k, xchr[k]);
318 show_line(log_line, 0);
324 char *replacement[MAXCHRS]; /* pointers to replacement strings */
326 void read_repl_sub (FILE * repl_input)
329 char buffer[PATH_MAX];
335 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
337 for (k = 0; k < MAXCHRS; k++) replacement[k] = NULL;
340 while (fgets(buffer, PATH_MAX, repl_input) != NULL) {
341 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
342 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
345 if (*charname == '"') { /* deal with quoted string "..." */
348 while (*s != '"' && *s != '\0') s++; /* step up to " */
349 if (*s++ == '\0') continue; /* sanity check */
352 s++; /* is it "" perhaps ? */
353 if (*s != '"') break; /* no, end of string */
355 *t++ = *s++; /* copy over */
357 *t = '\0'; /* and terminate */
359 if (chrs >= 0 && chrs < MAXCHRS)
360 replacement[chrs] = xstrdup(charname);
362 /* presently the following can never get triggered */
363 /* which is good, because it is perhaps not right ... */
364 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
365 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
366 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
367 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
368 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
370 if (chrs >= 0 && chrs < MAXCHRS)
371 replacement[chrs] = xstrdup(charname);
374 sprintf(log_line, "ERROR: don't understand %s", buffer);
375 show_line(log_line, 1);
378 if (trace_flag) { /* debugging output */
379 show_line("Key replacement table\n", 0);
380 for (k = 0; k < MAXCHRS; k++) {
381 if (replacement[k] != NULL) {
382 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
383 show_line(log_line, 0);
389 /* Following used both to read xchr[] file and key replacement file */
390 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
392 int read_xchr_file (char *filename, int flag, char *argv[])
395 char infile[PATH_MAX];
398 if (filename == NULL) return -1;
400 sprintf(log_line, "Reading xchr/repl %s\n", filename);
401 show_line(log_line, 0);
404 /* first try using file as specified */
405 strcpy(infile, filename);
407 sprintf(log_line, "Trying %s\n", infile);
408 show_line(log_line, 0);
410 if (share_flag == 0) pinput = fopen (infile, "r");
411 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
412 if (pinput == NULL) {
413 if (strrchr(infile, '.') == NULL) {
414 if (flag == 0) strcat(infile, ".map");
415 else strcat(infile, ".key");
417 sprintf(log_line, "Trying %s\n", infile);
418 show_line(log_line, 0);
420 if (share_flag == 0) pinput = fopen (infile, "r");
421 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
424 if (pinput == NULL) {
425 /* strcpy (infile, gargv[0]); */ /* try TeX program path */
426 strcpy (infile, argv[0]); /* try TeX program path */
427 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
428 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
429 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
430 strcat (infile, filename);
432 sprintf(log_line, "Trying %s\n", infile);
433 show_line(log_line, 0);
435 if (share_flag == 0) pinput = fopen (infile, "r");
436 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
437 if (pinput == NULL) {
438 if (strchr(infile, '.') == NULL) {
439 if (flag == 0) strcat(infile, ".map");
440 else strcat(infile, ".key");
442 sprintf(log_line, "Trying %s\n", infile);
443 show_line(log_line, 0);
445 if (share_flag == 0) pinput = fopen (infile, "r");
446 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
450 if (pinput == NULL) { /* 97/July/31 */
451 /* strcpy (infile, gargv[0]); */ /* try TeX program path\keyboard */
452 strcpy (infile, argv[0]); /* try TeX program path */
453 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
454 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
455 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
456 strcat (infile, "keyboard\\");
457 strcat (infile, filename);
459 sprintf(log_line, "Trying %s\n", infile);
460 show_line(log_line, 0);
462 if (share_flag == 0) pinput = fopen (infile, "r");
463 else pinput = _fsopen (infile, "r", share_flag);
464 if (pinput == NULL) {
465 if (strchr(infile, '.') == NULL) {
466 if (flag == 0) strcat(infile, ".map");
467 else strcat(infile, ".key");
469 sprintf(log_line, "Trying %s\n", infile);
470 show_line(log_line, 0);
472 if (share_flag == 0) pinput = fopen (infile, "r");
473 else pinput = _fsopen (infile, "r", share_flag);
477 /* Note: can't look in TeX source file dir, since that is not known yet */
478 if (pinput == NULL) {
479 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
480 flag ? " xchr[]" : "key mapping", filename);
481 show_line(log_line, 1);
482 perrormod (filename);
487 read_xchr_sub (pinput);
489 read_repl_sub (pinput);
491 (void) fclose (pinput);
495 /* need to also set `key_replace' here based on command line */
496 /* need to also allocate `buffercopy' here and free at end */
497 /* need to call `readreplace' in appropriate place */
499 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
501 /* Following may be useful if link without floating point emulation */
504 void testfloating (void)
506 /* double x = 1.0; */
507 /* double dx = DBL_EPSILON; */
511 /* while (x + dx != 1.0) { */
512 while (1.0 + dx != 1.0)
518 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
519 show_line(log_line, 0);
523 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
525 char *debugfile; /* NULL or name of file to try and open */
528 char *heapstrings[] =
530 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
534 /* Attempt to get at problem with eqtb ... temporarily abandoned */
536 void check_eqtb (char *act)
539 memory_word *eqtb = zeqtb;
540 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
541 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++)
543 if (eqtb[k].cint != 0)
548 show_line("EQTB ", 0);
550 sprintf(log_line, "%d ", k);
551 show_line(log_line, 0);
552 if (count++ > 256) break;
560 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
564 /* ad hoc default minimum growth in memory realloc is 62% */
565 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
566 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
567 int total_allocated = 0; /* total memory allocated so far */
568 int ini_max_address = 0; /* maximum address when starting */
569 int max_address = 0; /* maximum address seen in allocated memory */
573 // DON'T USE THIS in DLL VERSION
577 unsigned int heapthreshold=0; /* smallest size block interested in ... */
579 unsigned int heap_dump (FILE *output, int verbose)
581 unsigned int total=0;
582 struct _heapinfo hinfo;
587 if (verbose) fprintf(output, "HEAP DUMP:\n");
589 /* if ((n = _heapchk ()) != _HEAPOK) { */
596 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
598 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
601 hinfo._pentry = NULL;
602 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
604 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024)
606 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
608 end_block = (int) hinfo._pentry + hinfo._size;
609 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
610 if (hinfo._size >= heapthreshold && verbose)
611 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
612 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
613 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
619 if (verbose) fprintf(output, "OK - empty heap\n");
622 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
625 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
628 fprintf(output, "ERROR - %s\n", "bad start of heap");
631 fprintf(output, "ERROR - %s\n", "bad node in heap");
639 void show_maximums (FILE *output)
642 unsigned heaptotal=0; /* no longer used */
643 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
645 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
646 // if (output != NULL) fputs(log_line, output); // log file
647 // else if (flag == 0) show_line(log_line, 0); // informative
648 // else if (flag == 1) show_line(log_line, 1); // error
649 if (output == stderr)
650 show_line(log_line, 1);
651 else if (output == stdout)
652 show_line(log_line, 0);
654 fputs(log_line, output);
657 /* our own version of realloc --- avoid supposed MicroSoft version bug */
658 /* also tries _expand first, which can avoid address growth ... */
661 void *ourrealloc (void *old, size_t new_size)
664 size_t old_size, overlap;
666 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
667 if ((new_size % 4) != 0)
668 new_size = ((new_size / 4) + 1) * 4;
671 return malloc (new_size); /* no old block - use malloc */
673 old_size = _msize (old);
674 if (old_size >= new_size && old_size < new_size + 4)
676 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
680 show_line("BEFORE REALLOC: \n", 0);
682 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
686 mnew = _expand (old, new_size); /* first try and expand in place */
691 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
692 mnew, new_size, old, old_size);
693 show_line(log_line, 0);
697 /* *********************************************************************** */
698 /* do this if you want to call the real realloc next - */
699 mnew = realloc (old, new_size);
703 show_line("AFTER REALLOC: \n", 0);
705 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
711 /* we are screwed typically if we ever drop through here - no more space */
712 /* *********************************************************************** */
713 mnew = malloc (new_size); /* otherwise find new space */
715 return mnew; /* if unable to allocate */
716 if (old_size < new_size)
720 memcpy (mnew, old, overlap); /* copy old data to new area */
721 free(old); /* free the old area */
726 void memory_error (char *s, int n)
730 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
731 show_maximums(log_file);
734 (void) heap_dump(log_file, 1);
737 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
738 show_line(log_line, 1);
739 show_maximums(stderr);
742 (void) heap_dump(stderr, 1);
744 /* exit (1); */ /* 94/Jan/22 */
745 /* return to let TeX do its thing (such as complain about runaway) */
746 /* don't set abort_flag here */
749 void trace_memory (char *s, int n)
751 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
752 show_line(log_line, 0);
755 void update_statistics (int address, int size, int oldsize)
757 if (address + size > max_address)
758 max_address = address + size;
759 total_allocated = total_allocated + size - oldsize;
762 void probe_memory (void)
765 s = (char *) malloc (4); /* get current top address */
767 update_statistics ((int) s, 0, 0); /* show where we are */
770 void probe_show (void)
773 show_maximums(stdout);
776 (void) heap_dump(stdout, 1);
780 size_t roundup (size_t n)
785 return ((n / 4) + 1) * 4;
789 /* using allocating hyphenation trie slows things down maybe 1% */
790 /* but saves typically (270k - 55k) = 215k of memory */
791 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
792 /* since hyphenation trie cannot be extended (after iniTeX) */
793 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
795 /* NOTE: we don't ever reallocate these */
796 /* returns -1 if it fails */
798 int allocate_tries (int trie_max)
801 /* if (trie_max > trie_size) {
802 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
803 trie_max, trie_size);
804 show_line(log_line, 1);
806 } */ /* ??? removed 1993/dec/17 */
807 if (trie_max > 1000000)
808 trie_max = 1000000; /* some sort of sanity limit */
809 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
810 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
811 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
812 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
814 if (trace_flag) trace_memory("hyphen trie", n);
815 trie_trl = (halfword *) malloc (roundup(nl));
816 trie_tro = (halfword *) malloc (roundup(no));
817 trie_trc = (quarterword *) malloc (roundup(nc));
818 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
820 memory_error("hyphen trie", n);
825 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
826 show_line(log_line, 0);
828 update_statistics ((int) trie_trl, nl, 0);
829 update_statistics ((int) trie_tro, no, 0);
830 update_statistics ((int) trie_trc, nc, 0);
831 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
832 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
834 probe_show(); /* 94/Mar/25 */
839 #ifdef ALLOCATEHYPHEN
840 bool prime (int); /* test function later in this file */
842 int current_prime = 0; /* remember in case reallocated later */
844 /* we don't return an address here, since TWO memory regions allocated */
845 /* plus, we don't really reallocate, we FLUSH the old information totally */
846 /* returns -1 if it fails */
848 int realloc_hyphen (int hyphen_prime)
852 if (!prime(hyphen_prime))
854 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
855 show_line(log_line, 1);
859 /* need not/cannot preserve old contents when hyphen prime is changed */
860 /* if (hyph_list != NULL) free(hyph_list); */
861 /* if (hyph_word != NULL) free(hyph_word); */
862 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
863 nw = (hyphen_prime + 1) * sizeof(str_number);
864 nl = (hyphen_prime + 1) * sizeof(halfword);
867 trace_memory("hyphen exception", n);
868 /* initially hyph_word will be NULL so this acts like malloc */
869 /* hyph_word = (str_number *) malloc (nw); */
870 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
871 /* initially hyph_list will be NULL so this acts like malloc */
872 /* hyph_list = (halfword *) malloc (nl); */
873 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
875 if (hyph_word == NULL || hyph_list == NULL)
877 memory_error("hyphen exception", n);
882 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
883 show_line(log_line, 0);
885 /* cannot preserve old contents when hyphen prime is changed */
887 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
889 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
892 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
894 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
896 hyph_count = 0; /* or use reset_hyphen() in itex.c */
897 if (current_prime != 0)
899 update_statistics ((int) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
900 update_statistics ((int) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
904 update_statistics ((int) hyph_word, nw, 0);
905 update_statistics ((int) hyph_list, nl, 0);
907 current_prime = hyphen_prime;
908 if (trace_flag) probe_show(); /* 94/Mar/25 */
913 int current_mem_size=0; /* current total words in main mem allocated -1 */
915 /* this gets called from itex.c when it figures out what mem_top is */
916 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
917 /* initial allocation only, may get expanded later */
918 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
919 /* returns NULL if it fails */
922 /* initial main memory alloc - mem_top */
923 memory_word *allocate_main_memory (int size)
927 /* Using -i *and* pre-loading format */ /* in this case get called twice */
928 /* Get rid of initial blank memory again or use realloc ... */
929 /* Could we avoid this by detecting presence of & before allocating ? */
930 /* Also, if its already large enough, maybe we can avoid this ? */
931 /* don't bother if current_mem_size == mem_max - mem_start ? */
932 if (mainmemory != NULL)
934 /* free(mainmemory); */
935 /* mainmemory = NULL; */
936 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
937 /* if (mem_spec_flag)
938 show_line("Cannot change initial main memory size when format is read\n", 1);*/
941 mem_top = mem_bot + size;
942 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
943 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
946 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
947 if (mem_extra_low != 0 && !is_initex)
948 mem_start = mem_bot - mem_extra_low; /* increase main memory */
950 mem_start = 0; /* bottom of memory allocated by system */
951 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
952 mem_min = 0; /* bottom of area made available to TeX */
953 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
954 if (trace_flag) trace_memory("main memory", n);
955 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
956 /* normally mainmemory == NULL here so acts like malloc ... */
957 mainmemory = (memory_word *) REALLOC (mainmemory, n);
958 if (mainmemory == NULL) {
959 memory_error("initial main memory", n);
960 // exit (1); /* serious error */
964 sprintf(log_line, "Address main memory == %d\n", mainmemory);
965 show_line(log_line, 0);
968 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
970 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
971 show_line(log_line, 0);
973 update_statistics ((int) mainmemory, n,
974 (current_mem_size + 1) * sizeof (memory_word));
975 /* current_mem_size = (mem_max - mem_start + 1); */
976 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
977 if (trace_flag) probe_show(); /* 94/Mar/25 */
978 return zzzaa; /* same as zmem, mem 94/Jan/24 */
980 #endif /* end of ALLOCATEMAIN */
983 /* int firstallocation = 1; */
985 /* increase main memory allocation at low end and high end */
986 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
987 /* returns NULL if it fails */
989 memory_word *realloc_main (int losize, int hisize)
992 int newsize = 0; /* to quieten compiler */
993 int n = 0; /* to quieten compiler */
994 memory_word * newmemory = NULL; /* to quieten compiler */
996 /* if (losize == 0 && hisize > 0) runawayflag = 1;
997 else runawayflag = 0; */ /* 94/Jan/22 */
1000 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
1001 show_line(log_line, 0);
1004 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
1006 show_line("Please use `-m=...' on command line\n", 0);
1007 // abort_flag++; // ???
1011 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
1012 show_line(log_line, 0);
1014 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
1015 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
1016 // abort_flag++; // ???
1019 /* first allocation should expand *both* lo and hi */
1020 if (hisize == 0 && mem_end == mem_max) hisize = losize;
1021 if (losize == 0 && mem_start == mem_min) losize = hisize;
1022 /* try and prevent excessive frequent reallocations */
1023 /* while avoiding over allocation by too much */
1024 minsize = current_mem_size / 100 * percent_grow;
1025 if (losize + hisize < minsize) {
1026 if (losize > 0 && hisize > 0) {
1027 losize = minsize / 2;
1028 hisize = minsize / 2;
1030 else if (losize > 0) losize = minsize;
1031 else if (hisize > 0) hisize = minsize;
1033 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
1034 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
1036 for (k = 0; k < MAXSPLITS; k++) {
1037 newsize = current_mem_size + losize + hisize;
1038 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
1039 while (newsize >= max_mem_size) {
1040 losize = losize / 2; hisize = hisize / 2;
1041 newsize = current_mem_size + losize + hisize;
1044 n = (newsize + 1) * sizeof (memory_word);
1045 if (trace_flag) trace_memory("main memory", n);
1046 newmemory = (memory_word *) REALLOC (mainmemory, n);
1047 if (newmemory != NULL) break; /* did we get it ? */
1048 if (current_mem_size == 0) break; /* in case we ever use for initial */
1049 losize = losize / 2; hisize = hisize / 2;
1052 if (newmemory == NULL) {
1053 memory_error("main memory", n);
1054 return zzzaa; /* try and continue with TeX !!! */
1057 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1058 show_line(log_line, 0);
1061 /* shift everything upward to make space for new low area */
1063 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1064 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1065 show_line(log_line, 0);
1067 memmove (newmemory + losize, newmemory,
1068 /* current_mem_size * sizeof(memory_word)); */
1069 (current_mem_size + 1) * sizeof(memory_word));
1070 /* could reduce words moved by (mem_max - mem_end) */
1072 mainmemory = newmemory; /* remember for free later */
1073 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1074 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1075 update_statistics ((int) mainmemory, n,
1076 (current_mem_size + 1) * sizeof (memory_word));
1077 current_mem_size = newsize;
1078 if (current_mem_size != mem_max - mem_start) {
1079 show_line("ERROR: Impossible Memory Error\n", 1);
1081 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1082 else zzzaa = mainmemory;
1083 if (trace_flag) probe_show(); /* 94/Mar/25 */
1089 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1091 int current_font_mem_size=0;
1093 /* fmemoryword can be either halfword or memory_word */
1094 fmemoryword *realloc_font_info (int size)
1095 { /* number of memorywords */
1096 fmemoryword *newfontinfo=NULL;
1098 int newsize=0; /* to quieten compiler */
1099 int n=0; /* to quieten compiler */
1102 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1103 show_line(log_line, 0);
1105 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1106 /* during initial allocation current_font_mem_size == 0 */
1107 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1108 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1109 return font_info; /* pass it back to TeX 99/Fabe/4 */
1111 /* try and prevent excessive frequent reallocations */
1112 /* while avoiding over allocation by too much */
1113 /* minsize = current_font_mem_size / 2; */
1114 minsize = current_font_mem_size / 100 * percent_grow;
1115 if (size < minsize) size = minsize;
1116 if (size < initial_font_mem_size) size = initial_font_mem_size;
1118 for (k=0; k < MAXSPLITS; k++) {
1119 newsize = current_font_mem_size + size;
1120 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1121 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1122 n = (newsize + 1) * sizeof (fmemoryword);
1123 if (trace_flag) trace_memory("font_info", n);
1124 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1125 if (newfontinfo != NULL) break; /* did we get it ? */
1126 if (current_font_mem_size == 0) break; /* initial allocation must work */
1130 if (newfontinfo == NULL) {
1131 memory_error("font", n);
1132 return font_info; /* try and continue !!! */
1134 font_info = newfontinfo;
1136 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1137 show_line(log_line, 0);
1139 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1140 current_font_mem_size = newsize;
1141 if (trace_flag) probe_show(); /* 94/Mar/25 */
1146 #ifdef ALLOCATESTRING
1147 int current_pool_size=0;
1149 packed_ASCII_code *realloc_str_pool (int size)
1154 packed_ASCII_code *newstrpool=NULL;
1157 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1158 show_line(log_line, 0);
1160 if (current_pool_size == pool_size) {
1161 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1163 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1165 /* minsize = current_pool_size / 2; */
1166 minsize = current_pool_size / 100 * percent_grow;
1167 if (size < minsize) size = minsize;
1168 if (size < initial_pool_size) size = initial_pool_size;
1170 for (k = 0; k < MAXSPLITS; k++) {
1171 newsize = current_pool_size + size;
1172 if (newsize > pool_size) newsize = pool_size;
1173 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1174 n = (newsize + 1) * sizeof (packed_ASCII_code);
1175 if (trace_flag) trace_memory("str_pool", n);
1176 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1177 if (newstrpool != NULL) break; /* did we get it ? */
1178 if (current_pool_size == 0) break; /* initial allocation must work */
1179 size = size / 2; /* else can retry smaller */
1182 if (newstrpool == NULL) {
1183 memory_error("string pool", n);
1184 return str_pool; /* try and continue !!! */
1186 str_pool = newstrpool;
1187 update_statistics ((int) str_pool, n, current_pool_size);
1188 current_pool_size = newsize;
1190 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1191 show_line(log_line, 0);
1193 if (trace_flag) probe_show(); /* 94/Mar/25 */
1198 #ifdef ALLOCATESTRING
1199 int current_max_strings=0;
1201 pool_pointer *realloc_str_start (int size)
1206 pool_pointer *newstrstart=NULL;
1209 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1210 show_line(log_line, 0);
1212 if (current_max_strings == max_strings) {
1213 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1215 return str_start; /* pass it back to TeX 99/Fabe/4 */
1217 /* minsize = current_max_strings / 2; */
1218 minsize = current_max_strings / 100 * percent_grow;
1219 if (size < minsize) size = minsize;
1220 if (size < initial_max_strings) size = initial_max_strings;
1222 for (k = 0; k < MAXSPLITS; k++) {
1223 newsize = current_max_strings + size;
1224 if (newsize > max_strings) newsize = max_strings;
1225 /* important + 1 since str_start[maxstring + 1] originally */
1226 n = (newsize + 1) * sizeof (pool_pointer);
1227 if (trace_flag) trace_memory("str_start", n);
1228 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1229 if (newstrstart != NULL) break; /* did we get it ? */
1230 if (current_max_strings == 0) break; /* initial allocation must work */
1231 size = size / 2; /* otherwise can try smaller */
1234 if (newstrstart == NULL) {
1235 memory_error("string pointer", n);
1236 return str_start; /* try and continue */
1238 str_start = newstrstart;
1239 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1240 current_max_strings = newsize;
1242 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1243 show_line(log_line, 0);
1245 if (trace_flag) probe_show(); /* 94/Mar/25 */
1252 /* returns -1 if it fails */
1254 int allocate_ini (int size)
1255 { /* size == trie_size */
1256 int n, nl, no, nc, nr, nh, nt;
1257 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1258 no = (size + 1) * sizeof(trie_op_code);
1259 nc = (size + 1) * sizeof(packed_ASCII_code);
1260 /* nt = (size + 1) * sizeof(bool); */
1261 nt = (size + 1) * sizeof(char);
1262 n = nl + no + nc + nr + nh + nt;
1263 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1264 3 * sizeof(trie_pointer) + sizeof (char)); */
1265 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1266 trie_l = (trie_pointer *) malloc (roundup(nl));
1267 trie_o = (trie_op_code *) malloc (roundup(no));
1268 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1269 trie_r = (trie_pointer *) malloc (roundup(nr));
1270 trie_hash = (trie_pointer *) malloc (roundup(nh));
1271 /* trie_taken = (bool *) malloc (nt); */
1272 trie_taken = (char *) malloc (roundup(nt));
1273 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1274 trie_hash == NULL || trie_taken == NULL) {
1275 memory_error("iniTeX hyphen trie", n);
1276 // exit (1); /* serious error */
1280 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1281 trie_l, trie_o, trie_c);
1282 show_line(log_line, 0);
1283 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1284 trie_r, trie_hash, trie_taken);
1285 show_line(log_line, 0);
1287 update_statistics ((int) trie_l, nl, 0);
1288 update_statistics ((int) trie_o, no, 0);
1289 update_statistics ((int) trie_c, nc, 0);
1290 update_statistics ((int) trie_r, nr, 0);
1291 update_statistics ((int) trie_hash, nh, 0);
1292 update_statistics ((int) trie_taken, nt, 0);
1293 /* trie_size = size; */ /* ??? */
1294 if (trace_flag) probe_show(); /* 94/Mar/25 */
1295 return 0; // success
1299 #ifdef ALLOCATESAVESTACK
1300 int current_save_size=0;
1302 memory_word *realloc_save_stack (int size)
1306 memory_word *newsave_stack=NULL;
1309 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1310 show_line(log_line, 0);
1312 if (current_save_size == save_size) { /* arbitrary limit */
1313 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1315 return save_stack; /* let TeX handle the error */
1317 minsize = current_save_size / 100 * percent_grow;
1318 if (size < minsize) size = minsize;
1319 if (size < initial_save_size) size = initial_save_size;
1321 for (k = 0; k < MAXSPLITS; k++) {
1322 newsize = current_save_size + size;
1323 if (newsize > save_size) newsize = save_size;
1324 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1325 if (trace_flag) trace_memory("save_stack", n);
1326 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1327 if (newsave_stack != NULL) break; /* did we get it ? */
1328 if (current_save_size == 0) break; /* initial allocation must work */
1329 size = size / 2; /* else can retry smaller */
1332 if (newsave_stack == NULL) {
1333 memory_error("save stack", n);
1334 return save_stack; /* try and continue !!! */
1336 save_stack = newsave_stack;
1337 update_statistics ((int) save_stack, n, current_save_size);
1338 current_save_size = newsize;
1340 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1341 show_line(log_line, 0);
1342 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1343 show_line(log_line, 0);
1345 if (trace_flag) probe_show(); /* 94/Mar/25 */
1350 #ifdef ALLOCATEINPUTSTACK
1351 int current_stack_size=0; /* input stack size */
1353 in_state_record *realloc_input_stack (int size)
1357 in_state_record *newinputstack=NULL;
1360 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1361 show_line(log_line, 0);
1363 if (current_stack_size == stack_size) { /* arbitrary limit */
1364 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1368 minsize = current_stack_size / 100 * percent_grow;
1369 if (size < minsize) size = minsize;
1370 if (size < initial_stack_size) size = initial_stack_size;
1372 for (k = 0; k < MAXSPLITS; k++) {
1373 newsize = current_stack_size + size;
1374 if (newsize > stack_size) newsize = stack_size;
1375 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1376 if (trace_flag) trace_memory("input_stack", n);
1377 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1378 if (newinputstack != NULL) break; /* did we get it ? */
1379 if (current_stack_size == 0) break; /* initial allocation must work */
1380 size = size / 2; /* else can retry smaller */
1383 if (newinputstack == NULL) {
1384 memory_error("input stack", n);
1385 return input_stack; /* try and continue !!! */
1387 input_stack = newinputstack;
1388 update_statistics ((int) input_stack, n, current_stack_size);
1389 current_stack_size = newsize;
1391 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1392 show_line(log_line, 0);
1393 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1394 show_line(log_line, 0);
1396 if (trace_flag) probe_show(); /* 94/Mar/25 */
1401 #ifdef ALLOCATENESTSTACK
1402 int current_nest_size=0; /* current nest size */
1404 list_state_record *realloc_nest_stack (int size)
1408 list_state_record *newnest=NULL;
1411 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1412 show_line(log_line, 0);
1414 if (current_nest_size == nest_size) { /* arbitrary limit */
1415 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1417 return nest; /* let TeX handle the error */
1419 minsize = current_nest_size / 100 * percent_grow;
1420 if (size < minsize) size = minsize;
1421 if (size < initial_nest_size) size = initial_nest_size;
1423 for (k = 0; k < MAXSPLITS; k++) {
1424 newsize = current_nest_size + size;
1425 if (newsize > nest_size) newsize = nest_size;
1426 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1427 if (trace_flag) trace_memory("nest stack", n);
1428 newnest = (list_state_record *) REALLOC (nest, n);
1429 if (newnest != NULL) break; /* did we get it ? */
1430 if (current_nest_size == 0) break; /* initial allocation must work */
1431 size = size / 2; /* else can retry smaller */
1434 if (newnest == NULL) {
1435 memory_error("nest stack", n);
1436 return nest; /* try and continue !!! */
1439 update_statistics ((int) nest, n, current_nest_size);
1440 current_nest_size = newsize;
1442 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1443 show_line(log_line, 0);
1444 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1445 show_line(log_line, 0);
1447 if (trace_flag) probe_show(); /* 94/Mar/25 */
1452 #ifdef ALLOCATEPARAMSTACK
1453 int current_param_size=0; /* current param size */
1455 halfword *realloc_param_stack (int size)
1459 halfword *newparam=NULL;
1462 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1463 show_line(log_line, 0);
1465 if (current_param_size == param_size) { /* arbitrary limit */
1466 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1468 return param_stack; /* let TeX handle the error */
1470 minsize = current_param_size / 100 * percent_grow;
1471 if (size < minsize) size = minsize;
1472 if (size < initial_param_size) size = initial_param_size;
1474 for (k = 0; k < MAXSPLITS; k++) {
1475 newsize = current_param_size + size;
1476 if (newsize > param_size) newsize = param_size;
1477 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1478 if (trace_flag) trace_memory("param stack", n);
1479 newparam = (halfword *) REALLOC (param_stack, n);
1480 if (newparam != NULL) break; /* did we get it ? */
1481 if (current_param_size == 0) break; /* initial allocation must work */
1482 size = size / 2; /* else can retry smaller */
1485 if (newparam == NULL) {
1486 memory_error("param stack", n);
1487 return param_stack; /* try and continue !!! */
1489 param_stack = newparam;
1490 update_statistics ((int) param_stack, n, current_param_size);
1491 current_param_size = newsize;
1493 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1494 show_line(log_line, 0);
1495 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1496 show_line(log_line, 0);
1498 if (trace_flag) probe_show(); /* 94/Mar/25 */
1503 #ifdef ALLOCATEBUFFER
1504 int current_buf_size=0;
1506 ASCII_code *realloc_buffer (int size)
1510 ASCII_code *newbuffer=NULL;
1513 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1514 show_line(log_line, 0);
1516 if (current_buf_size == buf_size) { /* arbitrary limit */
1517 /* memory_error ("buffer", buf_size); */
1519 return buffer; /* pass it back to TeX 99/Fabe/4 */
1521 minsize = current_buf_size / 100 * percent_grow;
1522 if (size < minsize) size = minsize;
1523 if (size < initial_buf_size) size = initial_buf_size;
1525 for (k = 0; k < MAXSPLITS; k++) {
1526 newsize = current_buf_size + size;
1527 if (newsize > buf_size) newsize = buf_size;
1528 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1529 if (trace_flag) trace_memory("buffer", n);
1530 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1531 if (newbuffer != NULL) break; /* did we get it ? */
1532 if (current_buf_size == 0) break; /* initial allocation must work */
1533 size = size / 2; /* else can retry smaller */
1536 if (newbuffer == NULL) {
1537 memory_error("buffer", n);
1538 return buffer; /* try and continue !!! */
1541 update_statistics ((int) buffer, n, current_buf_size);
1543 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1545 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1547 current_buf_size = newsize;
1549 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1550 show_line(log_line, 0);
1551 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1552 show_line(log_line, 0);
1554 if (trace_flag) probe_show(); /* 94/Mar/25 */
1559 /* we used to allocate this one only to reduce the size of the PE file */
1560 /* not used anymore - NO advantage */
1562 #ifdef ALLOCATEDVIBUF
1563 eight_bits *allocatedvibuf (int size)
1565 eight_bits *dvi_buf;
1568 n = (size + 1) * sizeof(eight_bits);
1569 if (trace_flag) trace_memory("dvi_buf", n);
1570 dvi_buf = (eight_bits *) malloc (roundup(n));
1571 if (dvi_buf == NULL) {
1572 memory_error("dvi_buf", n);
1576 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1577 show_line(log_line, 0);
1579 update_statistics ((int) dvi_buf, n, 0);
1580 if (trace_flag) probe_show(); /* 94/Mar/25 */
1585 /* we used to allocate this one only to reduce the size of the PE file */
1586 /* it can be done without loss in performance, since register eqtb = zeqtb */
1587 #ifdef ALLOCATEZEQTB
1588 memory_word *allocatezeqtb (int k)
1593 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1594 if (trace_flag) trace_memory("eqtb", n);
1595 zeqtb = (memory_word *) malloc (roundup(n));
1596 if (zeqtb == NULL) {
1597 memory_error("eqtb", n);
1598 // exit (1); /* serious error */
1602 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1603 show_line(log_line, 0);
1605 update_statistics ((int) zeqtb, n, 0);
1606 if (trace_flag) probe_show(); /* 94/Mar/25 */
1611 /* here is the main memory allocation routine -- calls the above */
1612 /* returns -1 if it fails */
1613 /* allocate rather than static 93/Nov/26 */
1614 int allocate_memory (void)
1618 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1622 #error ERROR: Not ready for ALLOCATEHASH...
1625 /* probably not worth while/not a good idea allocating following */
1626 /* they are all rather small, and typically don't need expansion */
1627 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1629 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1630 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1631 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1633 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1634 zzzae = (htwohalves *) malloc (roundup(n));
1636 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1637 zzzae = (twohalves *) malloc (roundup(n));
1639 if (trace_flag) trace_memory("hash table", n);
1640 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1643 memory_error("hash table", n);
1644 // exit (1); /* serious error */
1645 return -1; /* serious error */
1648 n = (inputsize + 1) * sizeof(memory_word);
1649 if (trace_flag) trace_memory("input_stack", n);
1650 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1651 input_stack = (memory_word *) malloc (roundup(n));
1652 if (input_stack == NULL) {
1653 memory_error("input_stack", n);
1654 // exit (1); /* serious error */
1655 return -1; /* serious error */
1659 /* no real reason to allocate dvi_buf - no need to ever grow it */
1660 #ifdef ALLOCATEDVIBUF
1661 /* zdvibuf = NULL; */
1662 zdvibuf = allocatedvibuf (dvi_buf_size);
1663 if (zdvibuf == NULL) return -1;
1666 #ifdef ALLOCATEZEQTB
1668 #ifdef INCREASEFONTS
1669 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1670 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1672 /* zeqtb = allocatezeqtb (13507); */
1673 zeqtb = allocatezeqtb (hash_size + 4007);
1677 #ifdef ALLOCATEINPUTSTACK
1678 input_stack = NULL; /* new 1999/Jan/21 */
1679 current_stack_size = 0;
1680 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1683 #ifdef ALLOCATENESTSTACK
1684 nest = NULL; /* new 1999/Jan/21 */
1685 current_nest_size = 0;
1686 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1689 #ifdef ALLOCATEPARAMSTACK
1690 param_stack = NULL; /* new 1999/Jan/21 */
1691 current_param_size = 0;
1692 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1695 #ifdef ALLOCATESAVESTACK
1696 save_stack = NULL; /* new 1999/Jan/7 */
1697 current_save_size = 0;
1698 save_stack = realloc_save_stack (initial_save_size);
1702 buffer = NULL; /* need to do earlier */
1703 current_buf_size = 0;
1704 buffer = realloc_buffer (initial_buf_size);
1707 #ifdef ALLOCATESTRING
1709 current_pool_size = 0;
1711 current_max_strings = 0;
1712 /* need to create space because iniTeX writes in before reading pool file */
1713 /* for a start, puts in strings for 256 characters */
1714 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1716 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1717 str_pool = realloc_str_pool (initial_pool_size);
1718 str_start = realloc_str_start (initial_max_strings);
1722 /* the following can save a lot of the usual 800k fixed allocation */
1725 current_font_mem_size = 0;
1726 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1727 /* if ini-TeX we need to do it here - no format file read later */
1728 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1734 mem_min = mem_bot; /* just to avoid complaints in texbody */
1735 mem_top = mem_initex;
1737 /* allocate main memory here if this is iniTeX */
1738 /* otherwise wait for format undumping in itex.c ... */
1740 /* avoid this if format specified on command line ??? */
1741 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1742 mem = allocate_main_memory(mem_initex); /* made variable ! */
1745 return -1; /* serious error */
1749 /* now for the hyphenation exception stuff */
1750 #ifdef ALLOCATEHYPHEN
1753 /* this will be overridden later by what is in format file */
1754 hyphen_prime = default_hyphen_prime;
1755 /* non ini-TeX use assumes format will be read and that specifies size */
1758 if (new_hyphen_prime)
1759 hyphen_prime = new_hyphen_prime;
1760 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1765 /* now for memory for the part of the hyphenation stuff that always needed */
1766 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1767 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1768 #ifdef ALLOCATETRIES
1771 if (allocate_tries (trie_size))
1776 /* now for memory for hyphenation stuff needed only when running iniTeX */
1780 if (allocate_ini(trie_size))
1785 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1786 trie_c = NULL; /* (trie_size + 1) * char */
1787 trie_taken = NULL; /* (trie_size + 1) * bool */
1791 free(holeadr); /* create the hole */
1793 return 0; // success
1796 /* returns non-zero if error - done to test integrity of stack mostly */
1797 /* free in reverse order 93/Nov/26 */
1798 int free_memory (void)
1801 unsigned heaptotal=0;
1802 /* unsigned total; */
1804 if (trace_flag) show_line("free_memory ", 0);
1807 if (debug_flag) check_eqtb("free_memory");
1809 if (verbose_flag || trace_flag) show_maximums(stdout);
1811 if (heap_flag) (void) heap_dump(stdout, 1);
1815 heaptotal = (void) heap_dump(stdout, 0);
1817 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1818 heaptotal, max_address);
1819 show_line(log_line, 0);
1822 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1823 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1824 show_line(log_line, 0);
1826 /* following only needed to check consistency of heap ... useful debugging */
1827 if (trace_flag) show_line("Freeing memory again\n", 0);
1830 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1832 /* the following checks the heap integrity */
1834 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1836 #ifdef SHOWHEAPERROR
1838 if (n != _HEAPOK) { /* 94/Feb/18 */
1839 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1840 show_line(log_line, 1);
1841 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1842 show_line(log_line, 0);
1843 return n; /* non-zero and negative */ /* unreachable ??? */
1846 /* only free memory if safe ... additional check */
1849 if (trie_taken != NULL) free(trie_taken);
1850 if (trie_hash != NULL) free(trie_hash);
1851 if (trie_r != NULL) free(trie_r);
1852 if (trie_c != NULL) free(trie_c);
1853 if (trie_o != NULL) free(trie_o);
1854 if (trie_l != NULL) free(trie_l);
1856 trie_hash = trie_l = trie_r = NULL;
1861 #ifdef ALLOCATETRIES
1862 if (trie_trc != NULL) free (trie_trc);
1863 if (trie_tro != NULL) free (trie_tro);
1864 if (trie_trl != NULL) free (trie_trl);
1866 trie_tro = trie_trl = NULL;
1868 #ifdef ALLOCATEHYPHEN
1869 if (hyph_list != NULL) free(hyph_list);
1870 if (hyph_word != NULL) free(hyph_word);
1875 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1876 if (mainmemory != NULL) free(mainmemory);
1880 if (font_info != NULL) free(font_info);
1883 #ifdef ALLOCATESTRING
1884 if (str_start != NULL) free(str_start);
1885 if (str_pool != NULL) free(str_pool);
1891 if (zzzae != NULL) free(zzzae);
1895 #ifdef ALLOCATEDVIBUF
1896 if (zdvibuf != NULL) free(zdvibuf);
1899 #ifdef ALLOCATEZEQTB
1900 if (zeqtb != NULL) free(zeqtb);
1904 #ifdef ALLOCATEPARAMSTACK
1905 if (param_stack != NULL) free(param_stack);
1908 #ifdef ALLOCATENESTSTACK
1909 if (nest != NULL) free(nest);
1912 #ifdef ALLOCATEINPUTSTACK
1913 if (input_stack != NULL) free(input_stack);
1916 #ifdef ALLOCATESAVESTACK
1917 if (save_stack != NULL) free(save_stack);
1920 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1921 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1922 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1923 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1924 format_file = string_file = source_direct = NULL;
1925 if (dvi_file_name != NULL) free(dvi_file_name);
1926 if (log_file_name != NULL) free(log_file_name);
1927 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1934 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1935 if (x % 2 == 0) return false;
1936 for (k = 3; k < x; k = k + 2) {
1937 if (x % k == 0) return false;
1938 /* if (k * k > x) return true; */
1939 if (sum * 4 > x) return true;
1946 bool show_use=false;
1947 bool floating=false;
1949 void complainarg (int c, char *s)
1951 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1952 show_line(log_line, 1);
1953 show_use = 1; // 2000 June 21
1956 /* following is list of allowed command line flags and args */
1958 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1960 /* only 01234567.9 still left to take ... maybe recycle u */
1962 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1964 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1966 void reorderargs (int ac, char **av)
1967 { /* put in 1993/Dec/28 */
1970 // char takeargs[128]; /* large enough for all command line arg chars */
1971 char takeargs[256]; /* large enough for all command line arg chars */
1973 /* assumes arg pointers av[] are writeable */
1974 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1976 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1977 /* show_line("No arguments?\n", 0); */ /* debugging */
1978 return; /* no args ! */
1982 t = takeargs; /* list of those that take args */
1983 while (*s != '\0' && *(s+1) != '\0') {
1984 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1989 show_line(takeargs, 0);
1994 for (;;) { /* scan to end of command line args */
1995 if (*av[n] != '-') break;
1996 /* does it take an argument ? and is this argument next ? */
1998 *(av[n]+2) == '\0' &&
1999 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
2000 strchr(takeargs, *(av[n]+1)) != NULL)
2001 n += 2; /* step over it */
2006 for (;;) { /* look for more command line args */
2009 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
2010 while (m < ac && *av[m] != '-') m++; /* first command */
2012 /* does it take an argument ? and is this argument next ? */
2013 /* check first whether the `-x' is isolated, or arg follows directly */
2014 /* then check whether this is one of those that takes an argument */
2016 *(av[m]+2) == '\0' &&
2017 strchr(takeargs, *(av[m]+1)) != NULL) {
2018 s = av[m]; /* move command down before non-command */
2020 for (; m > n; m--) av[m+1] = av[m-1];
2023 n += 2; /* step over moved args */
2026 s = av[m]; /* move command down before non-command */
2027 for (; m > n; m--) av[m] = av[m-1];
2029 n++; /* step over moved args */
2034 int test_align (int address, int size, char *name)
2037 if (size > 4) n = address % 4;
2038 else n = address % size;
2040 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2041 show_line(log_line, 0);
2046 /* activate detailed checking of alignment when trace_flag is set */
2048 void check_fixed_align (int flag)
2050 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2051 show_line("PLEASE RECOMPILE ME!\n", 1);
2053 #ifdef CHECKALIGNMENT
2055 test_align ((int) &mem_top, 4, "mem_top");
2056 test_align ((int) &mem_max, 4, "mem_max");
2057 test_align ((int) &mem_min, 4, "mem_min");
2058 test_align ((int) &bad, 4, "bad");
2059 test_align ((int) &trie_size, 4, "trie_size");
2060 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2061 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2062 test_align ((int) &name_length, 4, "name_length");
2063 test_align ((int) &first, 4, "first");
2064 test_align ((int) &last, 4, "last");
2065 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2066 test_align ((int) &pool_ptr, 4, "pool_ptr");
2067 test_align ((int) &str_ptr, 4, "str_ptr");
2068 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2069 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2070 test_align ((int) &log_file, 4, "log_file");
2071 test_align ((int) &tally, 4, "tally");
2072 test_align ((int) &term_offset, 4, "term_offset");
2073 test_align ((int) &file_offset, 4, "file_offset");
2074 test_align ((int) &trick_count, 4, "trick_count");
2075 test_align ((int) &first_count, 4, "first_count");
2076 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2077 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2078 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2079 test_align ((int) &use_err_help, 4, "use_err_help");
2080 test_align ((int) &interrupt, 4, "interrupt");
2081 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2082 test_align ((int) &arith_error, 4, "arith_error");
2083 test_align ((int) &tex_remainder, 4, "tex_remainder");
2084 test_align ((int) &temp_ptr, 4, "temp_ptr");
2085 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2086 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2087 test_align ((int) &var_used, 4, "var_used");
2088 test_align ((int) &dyn_used, 4, "dyn_used");
2089 test_align ((int) &avail, 4, "avail");
2090 test_align ((int) &mem_end, 4, "mem_end");
2091 test_align ((int) &mem_start, 4, "mem_start");
2092 test_align ((int) &rover, 4, "rover");
2093 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2094 test_align ((int) &depth_threshold, 4, "depth_threshold");
2095 test_align ((int) &breadth_max, 4, "breadth_max");
2096 test_align ((int) &nest, sizeof(nest[0]), "nest");
2099 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2101 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2102 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2103 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2104 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2106 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2107 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2108 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2109 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2110 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2111 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2112 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2113 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2115 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2116 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2117 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2118 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2119 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2120 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2121 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2122 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2123 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2124 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2125 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2126 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2127 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2128 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2129 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2130 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2131 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2132 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2133 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2134 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2135 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2136 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2137 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2138 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2140 #ifdef ALLOCATEDVIBUF
2141 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2143 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2144 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2145 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2146 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2147 test_align ((int) &background, sizeof(background[0]), "background");
2148 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2149 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2150 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2151 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2152 test_align ((int) &hc, sizeof(hc[0]), "hc");
2153 test_align ((int) &hu, sizeof(hu[0]), "hu");
2154 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2155 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2157 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2158 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2159 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2160 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2162 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2163 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2164 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2165 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2166 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2168 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2169 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2170 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2171 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2175 void check_alloc_align (int flag) {
2176 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2177 show_line("PLEASE RECOMPILE ME!\n", 1);
2178 #ifdef CHECKALIGNMENT
2181 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2183 #ifndef ALLOCATEDVIBUF
2184 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2186 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2187 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2188 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2189 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2190 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2191 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2192 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2193 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2194 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2195 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2196 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2197 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2198 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2199 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2200 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2205 void showaddresses (void)
2209 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2210 show_line(log_line, 0);
2211 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2212 show_line(log_line, 0);
2213 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2214 show_line(log_line, 0);
2215 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2216 save_stack, input_stack, line_stack, param_stack);
2217 show_line(log_line, 0);
2218 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2219 font_check, font_size, font_dsize, font_params, font_name);
2220 show_line(log_line, 0);
2221 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2222 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2223 show_line(log_line, 0);
2227 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2229 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2230 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2232 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2233 bool backwardflag = false; /* don't cripple all advanced features */
2234 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2235 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2236 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2237 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2238 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2239 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2240 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2241 bool workingdirectory = false; /* if working directory set in ini */
2243 /* set up full file name for dviwindo.ini and check for [Environment] */
2244 bool setupdviwindo (void)
2246 char dviwindoini[PATH_MAX];
2247 char line[PATH_MAX];
2250 int em = strlen(envsection);
2251 int wm = strlen(wndsection);
2252 int dm = strlen(workdirect);
2256 /* Easy to find Windows directory if Windows runs */
2257 /* Or if user kindly set WINDIR environment variable */
2258 /* Or if running in Windows NT */
2259 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2260 (windir = getenv("WINDIR")) != NULL ||
2261 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2262 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2263 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2264 strcpy(dviwindoini, windir);
2265 strcat(dviwindoini, "\\");
2266 strcat(dviwindoini, inifilename);
2267 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2271 _searchenv (inifilename, "PATH", dviwindoini);
2272 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2275 wndflag = envflag = 0;
2276 /* workingdirectory = false; */
2277 if (*dviwindoini != '\0') {
2278 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2279 /* check whether dviwindo.ini actually has [Environment] section */
2280 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2281 else pinput = _fsopen(dviwindo, "r", share_flag);
2282 if (pinput != NULL) {
2283 while (fgets (line, sizeof(line), pinput) != NULL) {
2284 if (*line == ';') continue;
2285 if (*line == '\n') continue;
2287 if (wndflag && envflag) break; /* escape early */
2289 if (_strnicmp(line, wndsection, wm) == 0) {
2291 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2292 show_line(log_line, 0);
2296 else if (_strnicmp(line, envsection, em) == 0) {
2298 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2299 show_line(log_line, 0);
2301 /* fclose(input); */
2304 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2306 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2307 show_line(log_line, 0);
2309 workingdirectory = true;
2313 (void) fclose(pinput);
2317 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2318 (void) fclose(pinput);
2320 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2321 strcpy(dviwindo, ""); /* failed, for one reason or another */
2326 /* cache to prevent allocating twice in a row */
2328 char *lastname=NULL, *lastvalue=NULL;
2330 /* get value of env var - try first in dviwindo.ini then DOS env */
2331 /* returns allocated string -- these strings are not freed again */
2332 /* is it safe to do that now ? 98/Jan/31 */
2333 char *grabenv (char *varname)
2335 char line[PATH_MAX];
2339 /* int m = strlen(envsection); */
2340 /* int n = strlen(varname); */
2342 if (varname == NULL) return NULL; /* sanity check */
2343 if (*varname == '\0') return NULL; /* sanity check */
2344 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2345 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2346 if (lastname != NULL && _strcmpi(lastname, varname) == 0)
2350 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2351 show_line(log_line, 0);
2353 /* return lastvalue; */ /* save some time here */
2354 return xstrdup(lastvalue);
2355 /* duplicate so can free safely 98/Jan/31 */
2358 /* hmm, following was not xstrdup(...) */ /* not cached */
2359 if (usedviwindo == 0 || *dviwindo == '\0') {
2360 /* return getenv(varname); */
2361 s = getenv(varname);
2362 if (s == NULL) return NULL;
2363 else return xstrdup(s); /* make safe 98/Jan/31 */
2366 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2367 else pinput = _fsopen(dviwindo, "r", share_flag);
2369 if (pinput != NULL) {
2370 m = strlen(envsection);
2371 /* search for [Environment] section */ /* should be case insensitive */
2372 while (fgets (line, sizeof(line), pinput) != NULL) {
2373 if (*line == ';') continue;
2374 if (*line == '\n') continue;
2375 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2376 /* search for varname=... */ /* should be case sensitive ? */
2377 n = strlen(varname);
2378 while (fgets (line, sizeof(line), pinput) != NULL) {
2379 if (*line == ';') continue;
2380 if (*line == '[') break;
2381 /* if (*line == '\n') break; */ /* ??? */
2382 if (*line <= ' ') continue; /* 95/June/23 */
2383 /* if (strncmp(line, varname, n) == 0 && */
2384 if (_strnicmp(line, varname, n) == 0 &&
2385 *(line+n) == '=') { /* found it ? */
2386 (void) fclose (pinput);
2387 /* flush trailing white space */
2388 s = line + strlen(line) - 1;
2389 while (*s <= ' ' && s > line) *s-- = '\0';
2390 if (trace_flag) { /* DEBUGGING ONLY */
2391 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2392 show_line(log_line, 0);
2395 if (lastname != NULL) free(lastname);
2396 lastname = xstrdup (varname);
2397 if (lastvalue != NULL) free(lastvalue);
2398 lastvalue = xstrdup(s);
2399 return xstrdup(s); /* 98/Jan/31 */
2400 } /* end of matching varname */
2401 } /* end of while fgets */
2402 /* break; */ /* ? not found in designated section */
2403 } /* end of search for [Environment] section */
2405 (void) fclose (pinput);
2406 } /* end of if fopen */
2407 s = getenv(varname); /* failed, so try and get from environment */
2408 /* if (s != NULL) return s; */
2410 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2411 if (lastname != NULL) free(lastname);
2412 lastname = xstrdup (varname);
2413 if (lastvalue != NULL) free(lastvalue);
2414 lastvalue = xstrdup(s); /* remember in case asked again ... */
2416 return xstrdup(s); /* 98/Jan/31 */
2418 else return NULL; /* return NULL if not found anywhere */
2421 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2423 void flush_trailing_slash (char *directory)
2426 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2427 if (strcmp(directory, "") != 0) {
2428 s = directory + strlen(directory) - 1;
2429 if (*s == '\\' || *s == '/') *s = '\0';
2433 void knuthify (void)
2435 /* show_current = false; */ /* show ultimate limits */
2436 /* reorder_arg_flag = false; */ /* don't reorder command line */
2437 /* deslash = false; */ /* don't unixify file names */
2438 /* return_flag = false; */ /* don't allow just ^^M termination */
2439 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2440 restrict_to_ascii = false; /* don't complain non ASCII */
2441 allow_patterns = false; /* don't allow pattern redefinition */
2442 show_in_hex = true; /* show character code in hex */
2443 show_in_dos = false; /* redundant with previous */
2444 show_numeric = false; /* don't show character code decimal */
2445 show_missing = false; /* don't show missing characters */
2446 civilize_flag = false; /* don't reorder date fields */
2447 c_style_flag = false; /* don't add file name to error msg */
2448 show_fmt_flag = false; /* don't show format file in log */
2449 show_tfm_flag = false; /* don't show metric file in log */
2450 /* font_max = 255; */ /* revert to TeX 82 limit */
2451 /* if you want this, change in tex.h definition of font_max to `int' */
2452 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2454 show_line_break_stats = false; /* do not show line break stats */
2455 show_fonts_used = false;
2456 default_rule = 26214; /* revert to default rule thickness */
2457 pseudo_tilde = false;
2458 pseudo_space = false;
2459 show_texinput_flag = false;
2460 truncate_long_lines = false;
2461 allow_quoted_names = false;
2462 show_cs_names = false;
2463 font_dimen_zero = false; /* 98/Oct/5 */
2464 ignore_frozen = false; /* 98/Oct/5 */
2465 suppress_f_ligs = false; /* 99/Jan/5 */
2466 full_file_name_flag = false; // 00 Jun 18
2467 save_strings_flag = false; // 00 Aug 15
2468 knuth_flag = true; /* so other code can know about this */
2469 } /* end of knuthify */
2471 /* following have already been used up */
2473 /* abcdefghijklmnopqrstuvwxyz */
2475 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2479 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2481 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2483 /* following made global so analyze_flag can be made separate procedure */
2485 // char *xchrfile=""; /* save space use xstrdup */
2486 char *xchrfile = NULL; /* save space use xstrdup */
2487 // char *replfile="";/* save space use xstrdup */
2488 char *replfile = NULL;/* save space use xstrdup */
2490 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2492 /* analyze command line flag or argument */
2493 /* c is the flag letter itself, while optarg is start of arg if any */
2495 /* when making changes, revise allowedargs */
2498 int analyze_flag (int c, char *optarg)
2503 want_version = true;
2504 verbose_flag = true;
2510 interaction = batch_mode; /* quiet mode */
2513 interaction = nonstop_mode; /* run mode */
2516 interaction = scroll_mode; /* scroll mode */
2519 interaction = error_stop_mode; /* tex mode */
2522 backwardflag = true; /* 94/Jun/15 */
2523 knuthify(); /* revert to `standard' Knuth TeX */
2526 c_style_flag = true; /* C style error msg 94/Mar/21 */
2529 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2532 current_tfm = false; /* not look current dir for TFM */
2535 current_flag = false; /* not look current dir for files */
2538 show_missing = false; /* do not show missing 94/June/10 */
2541 deslash = false; /* flipped 93/Nov/18 */
2542 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2545 allow_patterns = true; /* 93/Nov/26 */
2546 /* reset_exceptions = true; */ /* 93/Dec/23 */
2548 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2550 show_in_hex = true; /* flipped 00/Jun/18 */
2553 show_in_dos = true; /* 96/Jan/26 */
2556 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2559 workingdirectory = true; /* use source dir 98/Sep/29 */
2562 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2565 show_fonts_used = false; /* 97/Dec/24 */
2568 shorten_file_name = true; /* 95/Feb/20 */
2571 show_cs_names = true; /* 98/Mar/31 */
2574 ignore_frozen = true; /* 98/Oct/5 */
2577 font_dimen_zero = false; /* 98/Oct/5 */
2580 show_texinput_flag = false; /* 98/Jan/28 */
2582 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2585 usedviwindo = false; /* 94/May/19 */
2588 show_line_break_stats = false; /* 96/Feb/8 */
2591 show_fmt_flag = false; /* 94/Jun/21 */
2594 format_specific = false; /* 95/Jan/7 */
2597 encoding_specific = false; /* 98/Oct/5 */
2600 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2602 /* following are pretty obscure */
2603 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2605 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2607 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2610 full_file_name_flag = false; // 00 Jun 18
2613 save_strings_flag = false; // 00 Aug 15
2615 /* following are unannounced options */ /* some may be recycled ... */
2620 quitflag++; /* 93/Dec/16 */
2622 /* The following are really obscure and should not be advertized */
2624 show_current = false; /* tex8 93/Dec/14 */
2627 show_numeric = false; /* 93/Dec/21 */
2630 civilize_flag = false; /* 93/Dec/16 */
2633 open_trace_flag = true; /* openinou 1994/Jan/8 */
2636 reorder_arg_flag = false; /* local */
2639 test_dir_access = false; /* 94/Feb/10 */
2642 dir_method = false; /* 94/Feb/10 */
2645 file_method = false; /* 94/Feb/13 */
2647 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2648 /* case 'X': nohandler++; break; */
2649 /* case 'f': waitflush = false; break; */
2650 /* case 'F': floating = true; break; */
2651 /* *********** following command line options take arguments ************** */
2654 mem_initex = mem_top;
2656 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2657 if (mem_initex == 0)
2658 complainarg(c, optarg);
2661 #ifdef VARIABLETRIESIZE
2664 trie_size = default_trie_size;
2666 trie_size = atoi(optarg); /* 93 Dec/1 */
2668 complainarg(c, optarg);
2671 #ifdef ALLOCATEHYPHEN
2674 new_hyphen_prime = hyphen_prime * 2;
2676 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2677 if (new_hyphen_prime == 0)
2678 complainarg(c, optarg);
2681 #ifdef ALLOCATEDVIBUF
2684 dvi_buf_size = default_dvi_buf_size;
2686 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2687 if (dvi_buf_size == 0)
2688 complainarg(c, optarg);
2695 percent_grow = atoi(optarg); /* 93/Dec/11 */
2696 if (percent_grow == 0)
2697 complainarg(c, optarg);
2703 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2704 if (pseudo_tilde > 255)
2706 else if (pseudo_tilde < 128)
2709 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2710 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2716 tab_step = atoi(optarg); /* 94/July/3 */
2718 complainarg(c, optarg);
2722 xchrfile = xstrdup("xchr.map");
2724 xchrfile = xstrdup(optarg);
2725 if (xchrfile == NULL || *xchrfile == '\0')
2726 complainarg(c, optarg);
2730 replfile = xstrdup("repl.key");
2732 replfile = xstrdup(optarg);
2733 if (replfile == NULL || *replfile == '\0')
2734 complainarg(c, optarg);
2736 /* more obscure stuff - ppssibly recycle */
2739 default_rule = 26214; /* 95/Oct/9 */
2741 default_rule = atoi(optarg); /* 95/Oct/9 */
2742 if (default_rule == 0)
2743 complainarg(c, optarg);
2749 complainarg(c, optarg);
2755 dvi_directory = xstrdup(optarg);
2756 if (strcmp(dvi_directory, "") == 0)
2757 complainarg(c, optarg);
2763 log_directory = xstrdup(optarg);
2764 if (strcmp(log_directory, "") == 0)
2765 complainarg(c, optarg);
2771 aux_directory = xstrdup(optarg);
2772 if (strcmp(aux_directory, "") == 0)
2773 complainarg(c, optarg);
2778 return -1; // failed to recognize
2784 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2785 //char *yytexcmd="yandytex.cmd";
2786 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2788 /* Try and read default command file - YANDYTEX.CMD */
2789 /* in current directory and then in directory of YANDYTEX */
2790 /* (does not make sense in TeX file directory) */
2791 /* since we don't yet know where that is ! */
2792 /* can't conveniently include this in output file either - not open yet */
2794 /* used both for yytex.cmd and @ indirect command line files */
2795 /* can this be reentered ? */
2797 /* supply extension if none */
2798 void yy_extension (char *fname, char *ext)
2801 if ((s = strrchr(fname, '.')) == NULL ||
2802 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2808 /* remove file name - keep only path - inserts '\0' to terminate */
2810 void strip_name (char *pathname)
2813 if ((s = strrchr(pathname, '\\')) != NULL);
2814 else if ((s = strrchr(pathname, '/')) != NULL);
2815 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2820 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2822 char *programpath = ""; /* pathname of program */
2823 /* redundant with texpath ? */
2825 /* The following does not deslashify arguments ? Do we need to ? */
2827 int read_commands (char *filename)
2829 char commandfile[PATH_MAX];
2831 char line[PATH_MAX];
2832 char *linedup; /* need to copy line to preserve args */
2838 /* Try first in current directory (or use full name as specified) */
2839 strcpy(commandfile, filename);
2840 yy_extension(commandfile, "cmd");
2841 if (share_flag == 0)
2842 command = fopen(commandfile, "r");
2844 command = _fsopen(commandfile, "r", share_flag);
2845 if (command == NULL) {
2846 /* If that fails, try in YANDYTeX program directory */
2847 strcpy(commandfile, programpath);
2848 /* don't need fancy footwork, since programpath non-empty */
2849 strcat(commandfile, "\\");
2850 strcat(commandfile, filename);
2851 yy_extension(commandfile, "cmd");
2852 if (share_flag == 0)
2853 command = fopen(commandfile, "r");
2855 command = _fsopen(commandfile, "r", share_flag);
2856 if (command == NULL) {
2857 /* perrormod(commandfile); */ /* debugging only */
2858 /* strcpy(commandfile, ""); */ /* indicate failed */
2859 return 0; /* no command line file YYTEX.CMD */
2863 /* allow for multiple lines --- ignore args that don't start with `-' */
2864 while (fgets(line, PATH_MAX, command) != NULL) {
2865 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2866 /* skip over comment lines and blank lines */
2867 if (*line == '%' || *line == ';' || *line == '\n') continue;
2868 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2869 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2870 linedup = xstrdup (line); /* 93/Nov/15 */
2871 if (linedup == NULL) {
2872 show_line("ERROR: out of memory\n", 1); /* read_commands */
2874 return -1; // failure
2876 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2878 if (*s == '-' || *s == '/') {
2881 /* if (*optarg = '=') optarg++; */
2882 if (*optarg == '=') optarg++;
2883 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2885 /* else break; */ /* ignore non-flag items */
2886 s = strtok(NULL, " \t\n\r"); /* go to next token */
2888 /* If you want to see command lines in file - put -v in the file */
2889 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2891 (void) fclose(command); /* no longer needed */
2892 return 1; // success
2895 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2897 /* try and read commands on command line */
2898 int read_command_line (int ac, char **av)
2901 char *optargnew; /* equal to optarg, unless that starts with `=' */
2902 /* in which case it is optarg+1 to step over the `=' */
2903 /* if optarg = 0, then optargnew = 0 also */
2905 // show_line("read_command_line\n", 0);
2906 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2908 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2909 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2910 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2911 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2912 if (optarg != 0 && *optarg == '=')
2913 optargnew = optarg+1;
2916 analyze_flag (c, optargnew);
2918 if (show_use || quitflag == 3) {
2919 // showversion (stdout);
2921 strcat(log_line, "\n");
2922 show_line(log_line, 0);
2923 stampcopy(log_line);
2924 strcat(log_line, "\n");
2925 show_line(log_line, 0);
2926 if (show_use) show_usage(av[0]);
2927 else if (quitflag == 3) {
2928 strcat(log_line, "\n");
2929 show_line(log_line, 0);
2932 return -1; // failure
2935 if (floating) testfloating(); /* debugging */
2938 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2939 if (read_xchr_file(replfile, 1, av)) {
2940 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2944 /* key_replace used in texmf.c (input_line) */
2945 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2946 if (read_xchr_file(xchrfile, 0, av)) {
2947 if (trace_flag) show_line("NON ASCII ON\n", 0);
2951 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2952 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2957 void uppercase (char *s)
2960 while ((c = *s) != '\0') {
2961 /* if (islower(c)) *s = toupper (*s); */
2968 int init_commands (int ac, char **av)
2970 /* NOTE: some defaults changed 1993/Nov/18 */
2971 /* want_version = show_use = switchflag = return_flag = false;
2972 is_initex = trace_flag = deslash = non_ascii = false; */
2973 is_initex = false; /* check for dumping format file */
2974 allow_patterns = false; /* using \pattern after format file loaded */
2975 reset_exceptions = false;
2977 key_replace = false;
2978 want_version = false;
2979 open_trace_flag = false;
2981 verbose_flag = false;
2983 restrict_to_ascii = false;
2984 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2985 show_in_dos = false; /* default is not to translate to DOS 850 */
2986 return_flag = true; // hard wired now
2987 trimeof = true; // hard wired now
2989 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2990 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2991 default_rule = 26214; /* default rule variable 95/Oct/9 */
2992 show_current = true;
2993 civilize_flag = true;
2994 show_numeric = true;
2995 show_missing = true;
2996 current_flag = true;
2997 current_tfm = true; /* search for TFMs in current dir as well */
2998 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2999 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
3000 file_method = true; /* use file_p (_findfirst) not readable (access) */
3001 /* waitflush = true; */ /* flushed 97/Dec/24 */
3002 c_style_flag = false; /* use c-style error output */
3003 show_fmt_flag = true; /* show format file in log */
3004 show_tfm_flag = false; /* don't show metric file in log */
3005 shorten_file_name = false; /* don't shorten file names to 8+3 */
3006 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
3007 truncate_long_lines = true; /* truncate long lines */
3008 tab_step = 0; /* do not replace tabs with spaces */
3009 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
3010 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
3011 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
3012 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
3013 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
3014 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
3015 knuth_flag = false; /* allow extensions to TeX */
3016 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
3017 full_file_name_flag = true; /* new default 2000 June 18 */
3018 save_strings_flag = true; // 2000 Aug 15
3019 errout = stdout; /* as opposed to stderr say --- used ??? */
3020 abort_flag = 0; // not yet hooked up ???
3021 err_level = 0; // not yet hooked up ???
3022 new_hyphen_prime = 0;
3023 #ifdef VARIABLETRIESIZE
3024 /* trie_size = default_trie_size; */
3030 #ifdef ALLOCATEDVIBUF
3033 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
3034 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
3035 share_flag = 0; /* revert to fopen for now */
3037 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
3038 programpath = xstrdup(av[0]); /* extract path executable */
3039 strip_name(programpath); /* strip off yandytex.exe */
3041 //format_name = "yandytex";
3042 format_name = "plain"; /* format name if specified on command line */
3046 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
3047 return -1; // in case of error
3049 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
3050 return -1; // in case of error
3052 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
3054 /* Print version *after* banner ? */ /* does this get in log file ? */
3056 // showversion (stdout);
3057 // showversion (log_line);
3059 strcat(log_line, "\n");
3060 show_line(log_line, 0);
3061 stampcopy(log_line);
3062 strcat(log_line, "\n");
3063 show_line(log_line, 0);
3065 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
3067 /* if we aren't including current directory in any directory lists */
3068 /* then makes no sense to avoid them separately for TFM files ... */
3069 /* (that is, the ./ is already omitted from the dir list in that case */
3070 if (!current_flag && !current_tfm)
3071 current_tfm = true; /* 94/Jan/24 */
3072 return 0; // success
3075 /* E sets environment variable ? */
3077 void initial_memory (void)
3079 /* set initial memory allocations */
3080 if (mem_extra_high < 0)
3082 if (mem_extra_low < 0)
3088 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3089 if (mem_extra_high != 0 || mem_extra_low != 0)
3091 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3092 mem_extra_high = 0; mem_extra_low = 0;
3098 if (mem_initex != 0)
3100 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3105 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3106 /* trie_size = 0; */
3109 if (mem_initex == 0)
3110 mem_initex = default_mem_top;
3112 trie_size = default_trie_size;
3113 /* Just in case user mistakenly specified words instead of kilo words */
3114 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3115 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3116 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3117 #ifdef ALLOCATEHIGH /* not used anymore */
3118 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3119 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3120 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3123 #ifdef ALLOCATELOW /* not used anymore */
3124 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3125 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3126 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3129 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3130 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3131 /* mem_initex = 2048 * 1024; */
3133 #ifdef ALLOCATEDVIBUF
3134 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3135 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3136 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3137 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3138 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3140 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3141 if (new_hyphen_prime > 0) {
3143 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3145 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3146 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3148 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3149 show_line(log_line, 0);
3153 if (percent_grow > 100) percent_grow = percent_grow - 100;
3154 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3155 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3158 /**********************************************************************/
3160 void perrormod (char *s)
3162 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3163 show_line(log_line, 1);
3169 fflush(stdout); /* ??? */
3170 fflush(stderr); /* ??? */
3171 (void) _getch(); /* ??? */
3175 void checkpause (int flag)
3178 int debug_pause = 0;
3179 /* don't stop if in Q (quiet) or R (run) mode */
3180 /* stop only in S (scroll) and T (TeX) mode */
3181 if (interaction >= 0 && interaction < 2)
3182 flag = 0; /* 98/Jun/30 */
3183 s = grabenv("DEBUGPAUSE");
3184 if (s != NULL) sscanf(s, "%d", &debug_pause);
3185 if (flag < 0) return;
3187 if (debug_pause || flag > 0) {
3190 show_line("Press any key to continue . . .\n", 0);
3197 void check_enter (int argc, char *argv[])
3200 char current[FILENAME_MAX];
3201 if (grabenv("DEBUGPAUSE") != NULL) {
3202 (void) _getcwd(current, sizeof(current));
3203 sprintf(log_line, "Current directory: `%s'\n", current);
3204 show_line(log_line, 0);
3205 for (m = 0; m < argc; m++) {
3206 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3207 show_line(log_line, 0);
3214 void checkexit (int n)
3221 /*************************************************************************/
3223 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3224 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3225 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3226 /* this is then undone in tex3.c both for fopen input and output */
3227 /* not ideal, since pseudo name appears in log and in error messages ... */
3229 void hidetwiddle (char *name)
3234 sprintf(log_line, "Hidetwiddle %s", name);
3235 show_line(log_line, 0);
3238 /* while (*s != '\0' && *s != ' ') { */
3239 while (*s != '\0') {
3240 if (*s == '~' && pseudo_tilde != 0)
3241 *s = (char) pseudo_tilde; /* typically 254 */
3242 else if (*s == ' ' && pseudo_space != 0)
3243 *s = (char) pseudo_space; /* typically 255 */
3248 sprintf(log_line, "=> %s\n", name);
3249 show_line(log_line, 0);
3254 void deslash_all (int ac, char **av)
3256 char buffer[PATH_MAX];
3259 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3260 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3262 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3264 check_enter(ac, av); /* 95/Oct/28 */
3266 /* environment variables for output directories (as in PC TeX) */
3268 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3269 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3270 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3271 if ((s = grabenv("TEXFMT")) != NULL) fmt_directory = s;
3272 if ((s = grabenv("TEXPDF")) != NULL) pdf_directory = s;
3274 strcpy(buffer, av[0]); /* get path to executable */
3275 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3276 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3277 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3278 s = buffer + strlen(buffer) - 1;
3279 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3280 texpath = xstrdup(buffer);
3282 /* Hmm, we may be operating on DOS environment variables here !!! */
3284 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3285 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3286 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3287 if (strcmp(fmt_directory, "") != 0) flush_trailing_slash (fmt_directory);
3288 if (strcmp(pdf_directory, "") != 0) flush_trailing_slash (pdf_directory);
3292 unixify (texpath); /* 94/Jan/25 */
3293 /* if output directories given, deslashify them also 1993/Dec/12 */
3294 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3295 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3296 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3297 if (strcmp(fmt_directory, "") != 0) unixify(fmt_directory);
3298 if (strcmp(pdf_directory, "") != 0) unixify(pdf_directory);
3301 /* deslash TeX source file (and format, if format specified) */
3302 /* and check args to see whether format was specified */
3304 /* NOTE: assuming that command line arguments are in writable memory ! */
3305 /* if (trace_flag || debug_flag)
3306 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3307 /* if (optind < ac) { */ /* bkph */
3308 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3310 if (trace_flag || debug_flag) {
3311 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3312 optind, av[optind], ac);
3313 show_line(log_line, 0);
3315 unixify(av[optind]);
3317 if (pseudo_tilde != 0 || pseudo_space != 0)
3318 hidetwiddle (av[optind]); /* 95/Sep/25 */
3319 /* For Windows NT, lets allow + instead of & for format specification */
3320 if (*av[optind] == '&' || *av[optind] == '+') {
3321 format_spec = 1; /* format file specified */
3322 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3323 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3324 if (optind + 1 < ac) {
3326 if (trace_flag || debug_flag) {
3327 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3328 optind+1, av[optind+1], ac);
3329 show_line(log_line, 0);
3331 unixify(av[optind+1]);
3333 if (pseudo_tilde != 0 || pseudo_space != 0)
3334 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3340 /* The above seems to assume that arguments that don't start with '-' */
3341 /* are file names or format names - what if type in control sequences? */
3343 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3345 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3346 /* interaction == 1 => nonstop mode (omit all stops) */
3347 /* interaction == 2 => scroll mode (omit error stops) */
3348 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3350 /* main entry point follows */
3352 /* this gets called pretty much right away in `main' in texmf.c */
3354 /* note: those optarg == 0 test don't really work ... */
3355 /* note: optarg starts at = in case of x=... */
3357 int init (int ac, char **av)
3359 char initbuffer[PATH_MAX];
3362 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3369 show_line("TEXDEBUG\n", 0);
3370 trace_flag = 1; /* 94/April/14 */
3373 if (sizeof(memory_word) != 8) { /* compile time test */
3374 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3375 show_line(log_line, 1);
3378 start_time = clock(); /* get time */
3379 main_time = start_time; /* fill in, in case file never opened */
3381 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3383 /* reset all allocatable memory pointers to NULL - in case we drop out */
3388 #ifdef ALLOCATEZEQTB
3394 #ifdef ALLOCATESAVESTACK
3397 #ifdef ALLOCATEDVIBUF
3400 #ifdef ALLOCATEBUFFER
3401 buffer = NULL; /* new 1999/Jan/7 need to do early */
3402 current_buf_size = 0;
3403 buffer = realloc_buffer (initial_buf_size);
3404 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3406 hyph_list = NULL; hyph_word = NULL;
3407 trie_taken = NULL; trie_hash = NULL;
3416 log_opened = false; /* so can tell whether opened */
3417 interaction = -1; /* default state => 3 */
3418 missing_characters = 0; /* none yet! */
3419 workingdirectory = false; /* set from dviwindo.ini & command line */
3420 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3421 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3422 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3423 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3424 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3426 if (reorder_arg_flag) reorderargs(ac, av);
3428 if (init_commands(ac, av))
3429 return -1; // failure
3431 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3433 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3434 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3435 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3436 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3437 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3439 first_pass_count = 0;
3440 second_pass_count = 0;
3441 final_pass_count = 0;
3442 paragraph_failed = 0;
3449 closed_already=0; // so can only do once
3451 if (trace_flag) show_line("Entering init (local)\n", 0);
3453 /* Print version *after* banner ? */ /* does this get in log file ? */
3455 probe_memory(); /* show top address */
3456 ini_max_address = max_address; /* initial max address */
3457 if (trace_flag) show_maximums(stdout);
3459 if (heap_flag) (void) heap_dump(stdout, 1);
3464 deslash_all(ac, av); /* deslash and note if format specified */
3466 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3470 if (format_spec && mem_spec_flag) {
3471 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3474 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3475 return -1; // if failed to allocate
3477 /* following is more or less useless since most all things not yet alloc */
3478 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3480 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3484 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3487 if (trace_flag) show_line("Leaving init (local)\n", 0);
3488 return 0; // success
3491 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3493 /* void show_inter_val (clock_t start, clock_t end) { */
3494 void show_inter_val (clock_t interval)
3496 /* clock_t interval; */
3497 /* int seconds, tenths; */
3498 /* int seconds, tenths, hundredth; */
3499 int seconds, tenths, hundredth, thousands;
3500 /* interval = end - start; */
3501 /* sanity check whether positive ? */
3502 if (interval >= CLK_TCK * 10) {
3503 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3504 seconds = tenths / 10;
3505 tenths = tenths % 10;
3506 sprintf(log_line, "%d.%d", seconds, tenths);
3507 show_line(log_line, 0);
3509 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3510 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3511 seconds = hundredth / 100;
3512 hundredth = hundredth % 100;
3513 sprintf(log_line, "%d.%02d", seconds, hundredth);
3514 show_line(log_line, 0);
3516 else if (interval > 0) { /* 94/Oct/4 */
3517 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3518 seconds = thousands / 1000;
3519 thousands = thousands % 1000;
3520 sprintf(log_line, "%d.%03d", seconds, thousands);
3521 show_line(log_line, 0);
3523 else show_line("0", 0); /* 95/Mar/1 */
3526 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3527 /* shows various times, warning about missing chars */
3529 int endit (int flag)
3532 finish_time = clock();
3533 if (missing_characters != 0) flag = 1;
3534 if (missing_characters) {
3536 "! There %s %d missing character%s --- see log file\n",
3537 (missing_characters == 1) ? "was" : "were", missing_characters,
3538 (missing_characters == 1) ? "" : "s");
3539 show_line(log_line, 0);
3541 if (free_memory() != 0) flag++;
3543 /* show per page time also ? */
3545 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3546 start_time, main_time, finish_time); */
3547 show_line("Total ", 0);
3548 /* show_inter_val(start_time, finish_time); */
3549 show_inter_val(finish_time - start_time);
3550 show_line(" sec (", 0);
3551 /* show_inter_val(start_time, main_time); */
3552 show_inter_val(main_time - start_time);
3553 show_line(" format load + ", 0);
3554 /* show_inter_val(main_time, finish_time); */
3555 show_inter_val(finish_time - main_time);
3556 show_line(" processing) ", 0);
3557 if (total_pages > 0) {
3558 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3559 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3560 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3561 show_inter_val ((finish_time - main_time) / total_pages);
3562 show_line(" sec per page", 0);
3572 /********************************************************************************/
3574 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3578 #define MAXCOLUMN 78
3580 void print_cs_name (FILE *output, int h)
3585 textof = hash[h].v.RH;
3586 if (textof == 0) return; /* ignore if text() == 0 */
3588 if (textcolumn != 0) {
3589 sprintf(log_line, ", ");
3590 if (output != NULL) fprintf(output, log_line);
3591 else show_line(log_line, 0);
3594 if (textcolumn + n + 2 >= MAXCOLUMN) {
3595 sprintf(log_line, "\n");
3596 if (output == stderr) show_line(log_line, 1);
3597 else if (output == stdout) show_line(log_line, 0);
3598 else fputs(log_line, output);
3602 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3605 if (output == stderr) show_line(log_line, 1);
3606 else if (output == stdout) show_line(log_line, 0);
3607 else fprintf(output, log_line);
3611 int compare_strn (int, int, int, int); /* in tex9.c */
3613 /* compare two csnames in qsort */
3615 int compare_cs (const void *cp1, const void *cp2)
3617 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3620 textof1 = hash[c1].v.RH;
3621 textof2 = hash[c2].v.RH;
3622 l1 = length(textof1);
3623 l2 = length(textof2);
3624 k1 = str_start[textof1];
3625 k2 = str_start[textof2];
3626 /* showstring (k1, l1); */
3627 /* showstring (k2, l2); */
3628 return compare_strn (k1, l1, k2, l2);
3633 /* Allocate table of indeces to allow sorting on csname */
3634 /* Allocate flags to remember which ones already listed at start */
3636 void print_cs_names (FILE *output, int pass)
3638 int h, k, ccount, repeatflag;
3640 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3642 if (pass == 0 && csused == NULL) {
3643 csused = (char *) malloc (nfcs);
3644 if (csused == NULL) return;
3646 memset(csused, 0, nfcs);
3648 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3653 for (h = hash_base + 1; h < nfcs; h++) {
3654 if (pass == 1 && csused[h]) continue;
3655 if (hash[h].v.RH != 0) {
3656 if (pass == 0) csused[h] = 1;
3661 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3662 ccount, (pass == 1) ? "new" : "");
3663 if (output == stderr) show_line(log_line, 1);
3664 else if (output == stdout) show_line(log_line, 0);
3665 else fprintf(output, log_line);
3667 if (ccount > 0) { /* don't bother to get into trouble */
3669 cnumtable = (int *) malloc (ccount * sizeof(int));
3670 if (cnumtable == NULL) return;
3673 /* for (h = 515; h < (hash_size + 780); h++) { */
3674 for (h = hash_base+1; h < nfcs; h++) {
3675 if (pass == 1 && csused[ h]) continue;
3676 if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3679 qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3682 for (k = 0; k < ccount; k++) {
3684 if (pass == 1 && csused[ h]) continue;
3685 print_cs_name(output, h);
3687 sprintf(log_line, "\n");
3688 if (output == stderr) show_line(log_line, 1);
3689 else if (output == stdout) show_line(log_line, 0);
3690 else fprintf(output, log_line);
3691 free((void *)cnumtable);
3694 if (pass == 1 && csused != NULL) {
3700 /***************** font info listing moved from TEX9.C ******************/
3702 void showstring (int k, int l)
3705 while (l-- > 0) *s++ = str_pool[k++];
3708 show_line(log_line, 0);
3711 /* compare two strings in str_pool (not null terminated) */
3712 /* k1 and k2 are positions in string pool */
3713 /* l1 and l2 are lengths of strings */
3715 int compare_strn (int k1, int l1, int k2, int l2)
3718 /* while (l1-- > 0 && l2-- > 0) { */
3719 while (l1 > 0 && l2 > 0) {
3722 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3723 if (c1 > c2) return 1;
3724 else if (c2 > c1) return -1;
3728 if (l1 > 0) return 1; /* first string longer */
3729 else if (l2 > 0) return -1; /* second string longer */
3730 return 0; /* strings match */
3733 /* compare two font names and their at sizes in qsort */
3735 int compare_fnt (const void *fp1, const void *fp2)
3737 int f1, f2, l1, l2, k1, k2, s;
3740 l1 = length(font_name[f1]);
3741 l2 = length(font_name[f2]);
3742 k1 = str_start[font_name[f1]];
3743 k2 = str_start[font_name[f2]];
3744 /* showstring (k1, l1); */
3745 /* showstring (k2, l2); */
3746 s = compare_strn (k1, l1, k2, l2);
3747 /* sprintf(log_line, "%d\n", s); */
3748 if (s != 0) return s;
3749 if (font_size[f1]> font_size[f2]) return 1;
3750 else if (font_size[f1]< font_size[f2]) return -1;
3751 return 0; /* should not ever get here */
3754 /* compare two font names */
3756 int compare_fnt_name (int f1, int f2)
3758 int l1, l2, k1, k2, s;
3759 l1 = length(font_name[f1]);
3760 l2 = length(font_name[f2]);
3761 k1 = str_start[font_name[f1]];
3762 k2 = str_start[font_name[f2]];
3763 /* showstring (k1, l1); */
3764 /* showstring (k2, l2); */
3765 s = compare_strn (k1, l1, k2, l2);
3766 /* sprintf(log_line, "%d\n", s); */
3770 /* decode checksum information */
3772 unsigned long checkdefault = 0x59265920; /* default signature */
3774 int decode_fourty (unsigned long checksum, char *codingvector)
3778 /* char codingvector[6+1]; */
3780 /* if (checksum == checkdefault) { */
3781 if (checksum == 0) {
3782 /* strcpy(codingvector, "unknown"); */
3783 strcpy(codingvector, "unknwn");
3786 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3787 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3788 strcpy (codingvector, "fixed "); /* if not specified ... */
3789 return 1; /* no info available */
3792 for (k = 0; k < 6; k++) {
3793 c = (int) (checksum % 40);
3794 checksum = checksum / 40;
3795 if (c <= 'z' - 'a')c = c + 'a';
3796 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3797 else if (c == 36) c = '-';
3798 else if (c == 37) c = '&';
3799 else if (c == 38) c = '_';
3800 else c = '.'; /* unknown */
3801 codingvector[5-k] = (char) c;
3803 codingvector[6] = '\0';
3805 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3806 return 0; /* encoding info returned in codingvector */
3809 double sclpnt (long x)
3812 pt = (double) x / 65536.0;
3813 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3817 // Shows list of fonts in log file
3819 void dvi_font_show(internal_font_number f, int suppressname)
3821 int a, l, k, n, for_end;
3822 unsigned long checksum;
3823 char checksumvector[8];
3826 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3827 /* fprintf (log_file, "%d ", suppressname); */
3828 /* suppressname = 0; */
3829 putc(' ', log_file);
3830 if (suppressname == 0) {
3831 a = length(font_area[f]);
3832 l = length(font_name[f]);
3833 k = str_start[font_area[f]];
3834 for_end = str_start[font_area[f]+ 1]- 1;
3835 if (k <= for_end) do {
3836 putc(str_pool[k], log_file);
3837 } while(k++ < for_end, stdout);
3838 k = str_start[font_name[f]];
3839 for_end = str_start[font_name[f]+ 1]- 1;
3840 if (k <= for_end) do {
3841 putc(str_pool[k], log_file);
3842 } while(k++ < for_end);
3845 for (k = a+l; k < 16; k++) putc(' ', log_file);
3846 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3847 fputs(buffer, log_file);
3848 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3849 if (suppressname == 0) {
3851 // n = strlen(log_file);
3852 for (k = n; k < 16; k++) putc(' ', log_file);
3853 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3854 font_check[f].b2) << 8 | font_check[f].b3;
3855 decode_fourty(checksum, checksumvector);
3856 fprintf(log_file, "encoding: %s..", checksumvector);
3858 putc('\n', log_file);
3861 /* Allocate table of indeces to allow sorting on font name */
3863 void show_font_info (void)
3865 int k, m, fcount, repeatflag;
3869 for (k = 1; k <= font_ptr; k++)
3870 if (font_used[k])fcount++;
3872 if (fcount == 0) return; /* don't bother to get into trouble */
3874 fnumtable = (short *) malloc (fcount * sizeof(short));
3876 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3878 fprintf(log_file, "\nUsed %d font%s:\n",
3879 fcount, (fcount == 1) ? "" : "s");
3882 for (k = 1; k <= font_ptr; k++)
3883 if (font_used[k])fnumtable[fcount++] = (short) k;
3885 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3888 for (m = 0; m < fcount; m++) {
3890 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3892 else repeatflag = 0;
3894 dvi_font_show(fnumtable[ m], repeatflag);
3897 free((void *)fnumtable);
3900 ////////////////////////////////////////////////////////////////////////////
3902 // Here follows the new stuff for the DLL version
3908 #define SHOWLINEBUFLEN 256
3910 char showlinebuf[SHOWLINEBUFLEN];
3912 // char log_line[MAXLINE];
3914 #define WHITESPACE " \t\n\r"
3916 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3918 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3920 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3921 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3922 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3924 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3926 void ClearShowBuffer (void)
3928 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3929 if (hConsoleWnd != NULL)
3930 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3934 // communicate with DVIWindo (for yandytex.dll)
3936 void show_line (char *line, int errflag) { /* 99/June/11 */
3939 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3940 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3941 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3943 // abort_flag++; // kill job in this case ???
3947 if (showlineinx > 0) ClearShowBuffer();
3949 if (hConsoleWnd != NULL)
3950 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3954 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3955 if (ret == IDCANCEL) {
3957 uexit(1); // dangerous reentry possibility ?
3962 // Provide means for buffering up individual characters
3964 void show_char (int chr) {
3965 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3966 showlinebuf[showlineinx++] = (char) chr;
3967 if (chr == '\n') ClearShowBuffer();
3970 void winshow(char *line) {
3971 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3974 void winerror (char *line) {
3976 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3977 if (ret == IDCANCEL) abort_flag++;
3980 // argument info constructed from command line
3986 // need to be careful here because of quoted args with spaces in them
3987 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3989 int makecommandargs (char *line)
3993 unsigned char *s, *t; // fix 2000 June 18
3995 if (line == NULL) return -1; /* sanity check */
3997 // winerror(line); // debugging only
3999 // s = strtok(line, WHITESPACE);
4000 // while (s != NULL) { /* count arguments */
4002 // s = strtok(NULL, WHITESPACE);
4007 while (*s != '\0') {
4008 while (*s <= 32 && *s > 0) s++;
4009 if (*s == '\0') break;
4011 while (*t > 32 && *t != '\"') t++;
4014 while (*t > 0 && *t != '\"') t++;
4015 if (*t == '\0') break;
4018 // xargv[xargc] = s;
4020 if (*t == '\0') break;
4025 if (xargc == 0) return -1; /* nothing to do */
4027 xargv = (char **) malloc(xargc * sizeof(char *));
4028 if (xargv == NULL) {
4029 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
4036 while (*s != '\0') {
4037 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
4038 if (*s == '\0') break;
4040 while (*t > ' ' && *t != '\"') t++;
4043 while (*t > 0 && *t != '\"') t++;
4044 if (*t == '\0') break;
4047 // winerror(s); // debugging only
4050 if (*t == '\0') break;
4056 // for (k = 0; k < xargc; k++) { /* create pointers to args */
4057 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
4059 // s += strlen(s) +1;
4065 for (k = 0; k < xargc; k++) {
4066 sprintf(s, "%d\t%s\n", k, xargv[k]);
4074 // refers to TeXAsk in dviwindo.c
4076 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4077 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
4079 // called from tex0.c only --- by initterm and term_input
4081 //int ConsoleInput (char *question, char *buffer)
4082 int ConsoleInput (char *question, char *help, char *buffer)
4086 if (AskUserCall == NULL) return 0;
4087 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4088 // show_line(log_line, 1);
4091 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
4092 // strcpy(buffer, "x");
4093 // strcat(buffer, " "); // ???
4094 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4095 // show_line(log_line, 1);
4096 // input_line_finish(); // ???
4097 // s = buffer + strlen(buffer);
4098 // *s++ = ' '; // space terminate
4099 // *s++ = '\0'; // and null terminate
4100 // returning != 0 means EOF or ^Z
4104 // This is the new entry point of DLL called from DVIWindo
4105 // ARGS: console window to send messages to, command line, callback fun
4106 // no console window output if hConsole is NULL
4107 // returns -1 if it fails --- returns 0 if it succeeds
4109 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4110 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4114 abort_flag = 0; // redundant
4115 hConsoleWnd = NULL; // redundant
4117 AskUserCall = AskUser; // remember callback
4119 hConsoleWnd = hConsole; // remember console window handle
4121 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4122 // if (grabenv("DEBUGPAUSE") != NULL) {
4123 // show_line(line, 0); // debugging - show command line
4124 // show_line("\n", 0);
4127 xargc = makecommandargs(line); // sets up global *xargv[]
4129 if (xargc < 0) return -1; // sanity check
4131 if (hConsoleWnd != NULL)
4132 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4133 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4136 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
4138 if (err_level > 0 || abort_flag > 0) {
4139 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4140 // err_level, abort_flag);
4141 // winerror(log_line);
4144 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
4145 // if (psbufpos > 0) PSputs("", output); // output already closed
4147 if (hConsoleWnd != NULL) {
4148 if (err_level > 0 || abort_flag > 0) flag = 1;
4149 else flag = 0; // pass along error indication
4150 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
4152 // PScallback = NULL;
4155 if (xargv != NULL) free(xargv);
4156 if (abort_flag) return -1;
4160 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4163 switch (fdwReason) {
4164 case DLL_PROCESS_ATTACH:
4165 // The DLL is being mapped into the process's address space
4166 // place to allocate memory ???
4167 // return FALSE if this fails
4168 hInstanceDLL = hInstDll; /* remember it */
4171 case DLL_THREAD_ATTACH:
4172 // A thread is being created
4175 case DLL_THREAD_DETACH:
4176 // A thread is exiting cleanly
4179 case DLL_PROCESS_DETACH:
4180 // The DLL is being unmapped from the process's address space
4181 // place to free any memory allocated
4182 // but make sure it in fact *was* allocated
4183 hInstanceDLL = NULL; /* forget it */
4186 return(TRUE); // used only for DLL_PROCESS_ATTACH
4188 #endif // end of new stuff for DLL version
4190 //////////////////////////////////////////////////////////////////////////////
4194 /* NOTE: current_tfm = false (-c)
4195 not checking for TFM in current directory saves 0.1 sec
4196 (0.2 if file_method = false (-G) */
4198 /* NOTE: test_dir_access = false (-b):
4199 not checking whether readable file is a directory saves maybe 0.5 sec
4200 BUT only if file_method = false (-G) - otherwise its irrelevant */
4202 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4203 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4204 BUT not if current_tfm = false (-c) */
4206 /* NOTE: file_method = false (-G) --- method for checking file accessible
4207 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4209 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4211 /* constants for _heapchk/_heapset/_heapwalk routines */
4212 /* #define _HEAPEMPTY (-1) */
4213 /* #define _HEAPOK (-2) */
4214 /* #define _HEAPBADBEGIN (-3) */
4215 /* #define _HEAPBADNODE (-4) */
4216 /* #define _HEAPEND (-5) */
4217 /* #define _HEAPBADPTR (-6) */
4219 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4221 /* buffercopy no longer used */
4223 /* To Knuthian reset right when command line interpreted */