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 */
121 char *texpath = ""; /* path to executable - used if env vars not set */
123 // #define MAXLINE 256
125 char log_line[MAXLINE]; // used also in tex9.c
127 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
128 int format_spec = 0; /* non-zero if a format specified on command line */
129 int closed_already = 0; /* make sure we don't try this more than once */
130 bool reorder_arg_flag = true; /* put command line flags/arguments first */
132 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
133 /* Used in tex0.c with wintodos[c-128] */
135 unsigned char wintodos[128] = {
136 0, 0, 0, 159, 0, 0, 0, 0,
137 94, 0, 0, 0, 0, 0, 0, 0,
138 0, 96, 39, 0, 0, 7, 0, 0,
139 126, 0, 0, 0, 0, 0, 0, 0,
140 32, 173, 189, 156, 207, 190, 221, 21,
141 0, 184, 166, 174, 170, 45, 169, 0,
142 248, 241, 253, 252, 0, 230, 20, 250,
143 0, 251, 167, 175, 172, 171, 243, 168,
144 183, 181, 182, 199, 142, 143, 146, 128,
145 212, 144, 210, 211, 222, 214, 215, 216,
146 209, 165, 227, 224, 226, 229, 153, 158,
147 157, 235, 233, 234, 154, 237, 232, 225,
148 133, 160, 131, 198, 132, 134, 145, 135,
149 138, 130, 136, 137, 141, 161, 140, 139,
150 208, 164, 149, 162, 147, 228, 148, 246,
151 155, 151, 163, 150, 129, 236, 231, 152
154 void show_usage (char * program) {
157 " yandytex [-?ivnwdrzpK] [-m=ini_mem] [-e=hyph_size] [-h=trie_size]\n"
158 " [-x=xchr_file] [-k=key_file] [-o=dvi_dir] [-l=log_dir] [-a=aux_dir]\n"
159 " [+format_file] [tex_file]\n\n"
160 " -? show this usage summary\n"
161 " -i start up as iniTeX (create format file)\n"
162 " -v be verbose (show implementation version number)\n"
163 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
164 " -w do not show `non ASCII' characters in hexadecimal (show as is)\n"
165 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
166 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
167 " -p allow use of \\patterns after loading format (iniTeX only)\n"
168 " -K disable all extensions to basic TeX\n"
169 " -m initial main memory size in kilo words (iniTeX only)\n"
170 " -e hyphenation exception dictionary size (iniTeX only)\n"
171 " -h hyphenation pattern trie size (iniTeX only)\n"
172 " -x use `non ASCII' character mapping (xchr[]) defined in file\n"
173 " -k use `key replacement' defined in file\n"
174 " -o write DVI file in specified directory (default current directory)\n"
175 " -l write LOG file in specified directory (default current directory)\n"
176 " -a write AUX file in specified directory (default current directory)");
178 show_line(log_line, 1);
180 uexit(1); // has this been setup yet ???
184 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
186 /* -c prepend current directory (.) to TFM directory list\n\ */
187 /* -b check that files with read access are not actually directories\n\ */
189 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
190 /* \t\t(applies to file name and format file name, if present)\n\ */
191 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
193 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
195 /* Sep 27 1990 => 1990 Sep 27 */
196 /* 012456789 0123456789 */
198 void scivilize (char * date)
202 strcpy (pyear, date + 7);
203 for (k = 5; k >= 0; k--) date[k + 5] = date[k];
204 for (k = 0; k < 4; k++) date[k] = pyear[k];
206 if (date[9] == ' ') date[9] = '0'; /* replace space by '0' */
210 /* Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35 */
212 void lcivilize (char * date)
217 strcpy (pyear, date + 20);
218 for (k = 18; k >= 0; k--) date[k+1] = date[k];
219 /* date[20] = '\n'; */
220 /* date[21] = '\0'; */
222 for (k = 0; k < 4; k++) date[k] = pyear[k];
227 // void stamp_it (FILE *outfile)
228 // now writes result into given buffer
229 void stamp_it (char *s)
233 strcpy(date, compiledate);
235 sprintf(s, "%s %s ", application, yandyversion);
237 sprintf(s, "(compiled time: %s %s)", date, compiletime);
241 void stampcopy (char *s)
244 sprintf(s, "%s %s", copyright, www); /* 99/Oct/25 */
248 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
253 void read_xchr_sub (FILE * xchr_input)
255 char buffer[PATH_MAX];
256 int k, from, to, count = 0;
260 memset (xchr, NOTDEF, MAXCHRS); /* mark unused */
262 for (k = 0; k < MAXCHRS; k++) xchr[k]= -1; /* mark unused */
265 memset (xord, NOTDEF, MAXCHRS); /* mark unused */
267 for (k = 0; k < MAXCHRS; k++) xord[k]= -1; /* mark unused */
270 #ifdef ALLOCATEBUFFER
271 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
273 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
276 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
277 /* if (sscanf (buffer, "%d %d", &from, &to) < 2)
278 sprintf(log_line, "Do not understand: %s", buffer); */
279 from = (int) strtol (buffer, &s, 0);
280 to = (int) strtol (s, NULL, 0);
281 /* what if line is bad ? do we just get from = 0 and to = 0 ? */
282 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS) {
283 if (xchr[from]== (unsigned char) NOTDEF)
284 xchr[from]= (unsigned char) to;
286 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
287 show_line(log_line, 0);
289 if (xord[to]== NOTDEF)
290 xord[to]= (unsigned char) from;
292 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
293 show_line(log_line, 0);
298 /* now fill in the gaps */ /* not clear this is a good idea ... */
299 for (k = 0; k < MAXCHRS; k++) {
300 if (xchr[k]== NOTDEF) { /* if it has not been filled */
301 if (xord[k]== NOTDEF) { /* see whether used already */
302 xchr[k]= (unsigned char) k; /* no, so make identity */
303 xord[k]= (unsigned char) k; /* no, so make identity */
307 xchr[NOTDEF]= NOTDEF; /* fixed point of mapping */
309 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
310 show_line(log_line, 0);
311 for (k = 0; k < MAXCHRS; k++) {
312 if (xchr[k]!= NOTDEF) {
313 sprintf(log_line, "%d => %d\n", k, xchr[k]);
314 show_line(log_line, 0);
320 char *replacement[MAXCHRS]; /* pointers to replacement strings */
322 void read_repl_sub (FILE * repl_input)
325 char buffer[PATH_MAX];
331 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
333 for (k = 0; k < MAXCHRS; k++) replacement[k] = NULL;
336 while (fgets(buffer, PATH_MAX, repl_input) != NULL) {
337 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
338 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
341 if (*charname == '"') { /* deal with quoted string "..." */
344 while (*s != '"' && *s != '\0') s++; /* step up to " */
345 if (*s++ == '\0') continue; /* sanity check */
348 s++; /* is it "" perhaps ? */
349 if (*s != '"') break; /* no, end of string */
351 *t++ = *s++; /* copy over */
353 *t = '\0'; /* and terminate */
355 if (chrs >= 0 && chrs < MAXCHRS)
356 replacement[chrs] = xstrdup(charname);
358 /* presently the following can never get triggered */
359 /* which is good, because it is perhaps not right ... */
360 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
361 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
362 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
363 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
364 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
366 if (chrs >= 0 && chrs < MAXCHRS)
367 replacement[chrs] = xstrdup(charname);
370 sprintf(log_line, "ERROR: don't understand %s", buffer);
371 show_line(log_line, 1);
374 if (trace_flag) { /* debugging output */
375 show_line("Key replacement table\n", 0);
376 for (k = 0; k < MAXCHRS; k++) {
377 if (replacement[k] != NULL) {
378 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
379 show_line(log_line, 0);
385 /* Following used both to read xchr[] file and key replacement file */
386 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
388 int read_xchr_file (char *filename, int flag, char *argv[])
391 char infile[PATH_MAX];
394 if (filename == NULL) return -1;
396 sprintf(log_line, "Reading xchr/repl %s\n", filename);
397 show_line(log_line, 0);
400 /* first try using file as specified */
401 strcpy(infile, filename);
403 sprintf(log_line, "Trying %s\n", infile);
404 show_line(log_line, 0);
406 if (share_flag == 0) pinput = fopen (infile, "r");
407 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
408 if (pinput == NULL) {
409 if (strrchr(infile, '.') == NULL) {
410 if (flag == 0) strcat(infile, ".map");
411 else strcat(infile, ".key");
413 sprintf(log_line, "Trying %s\n", infile);
414 show_line(log_line, 0);
416 if (share_flag == 0) pinput = fopen (infile, "r");
417 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
420 if (pinput == NULL) {
421 /* strcpy (infile, gargv[0]); */ /* try TeX program path */
422 strcpy (infile, argv[0]); /* try TeX program path */
423 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
424 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
425 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
426 strcat (infile, filename);
428 sprintf(log_line, "Trying %s\n", infile);
429 show_line(log_line, 0);
431 if (share_flag == 0) pinput = fopen (infile, "r");
432 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
433 if (pinput == NULL) {
434 if (strchr(infile, '.') == NULL) {
435 if (flag == 0) strcat(infile, ".map");
436 else strcat(infile, ".key");
438 sprintf(log_line, "Trying %s\n", infile);
439 show_line(log_line, 0);
441 if (share_flag == 0) pinput = fopen (infile, "r");
442 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
446 if (pinput == NULL) { /* 97/July/31 */
447 /* strcpy (infile, gargv[0]); */ /* try TeX program path\keyboard */
448 strcpy (infile, argv[0]); /* try TeX program path */
449 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
450 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
451 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
452 strcat (infile, "keyboard\\");
453 strcat (infile, filename);
455 sprintf(log_line, "Trying %s\n", infile);
456 show_line(log_line, 0);
458 if (share_flag == 0) pinput = fopen (infile, "r");
459 else pinput = _fsopen (infile, "r", share_flag);
460 if (pinput == NULL) {
461 if (strchr(infile, '.') == NULL) {
462 if (flag == 0) strcat(infile, ".map");
463 else strcat(infile, ".key");
465 sprintf(log_line, "Trying %s\n", infile);
466 show_line(log_line, 0);
468 if (share_flag == 0) pinput = fopen (infile, "r");
469 else pinput = _fsopen (infile, "r", share_flag);
473 /* Note: can't look in TeX source file dir, since that is not known yet */
474 if (pinput == NULL) {
475 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
476 flag ? " xchr[]" : "key mapping", filename);
477 show_line(log_line, 1);
478 perrormod (filename);
483 read_xchr_sub (pinput);
485 read_repl_sub (pinput);
487 (void) fclose (pinput);
491 /* need to also set `key_replace' here based on command line */
492 /* need to also allocate `buffercopy' here and free at end */
493 /* need to call `readreplace' in appropriate place */
495 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
497 /* Following may be useful if link without floating point emulation */
500 void testfloating (void) {
501 /* double x = 1.0; */
502 /* double dx = DBL_EPSILON; */
506 /* while (x + dx != 1.0) { */
507 while (1.0 + dx != 1.0) {
512 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
513 show_line(log_line, 0);
517 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
519 char *debugfile; /* NULL or name of file to try and open */
522 char *heapstrings[] = {
523 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
527 /* Attempt to get at problem with eqtb ... temporarily abandoned */
530 void check_eqtb (char *act) {
532 memory_word *eqtb = zeqtb;
533 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
534 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
535 if (eqtb[k].cint != 0) {
538 show_line("EQTB ", 0);
540 sprintf(log_line, "%d ", k);
541 show_line(log_line, 0);
542 if (count++ > 256) break;
545 if (count != 0) show_char('\n');
549 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
553 /* ad hoc default minimum growth in memory realloc is 62% */
554 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
555 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
556 int total_allocated = 0; /* total memory allocated so far */
557 int ini_max_address = 0; /* maximum address when starting */
558 int max_address = 0; /* maximum address seen in allocated memory */
562 // DON'T USE THIS in DLL VERSION
566 unsigned int heapthreshold=0; /* smallest size block interested in ... */
568 unsigned int heap_dump (FILE *output, int verbose)
570 unsigned int total=0;
571 struct _heapinfo hinfo;
576 if (verbose) fprintf(output, "HEAP DUMP:\n");
578 /* if ((n = _heapchk ()) != _HEAPOK) { */
584 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
586 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
589 hinfo._pentry = NULL;
590 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
591 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
592 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
594 end_block = (int) hinfo._pentry + hinfo._size;
595 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
596 if (hinfo._size >= heapthreshold && verbose)
597 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
598 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
599 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
602 switch (heapstatus) {
604 if (verbose) fprintf(output, "OK - empty heap\n");
607 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
610 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
613 fprintf(output, "ERROR - %s\n", "bad start of heap");
616 fprintf(output, "ERROR - %s\n", "bad node in heap");
624 void show_maximums (FILE *output)
627 unsigned heaptotal=0; /* no longer used */
628 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
630 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
631 // if (output != NULL) fputs(log_line, output); // log file
632 // else if (flag == 0) show_line(log_line, 0); // informative
633 // else if (flag == 1) show_line(log_line, 1); // error
634 if (output == stderr) show_line(log_line, 1);
635 else if (output == stdout) show_line(log_line, 0);
636 else fputs(log_line, output);
639 /* our own version of realloc --- avoid supposed MicroSoft version bug */
640 /* also tries _expand first, which can avoid address growth ... */
643 void *ourrealloc (void *old, size_t new_size)
646 size_t old_size, overlap;
648 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
649 if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
651 if (old == NULL) return malloc (new_size); /* no old block - use malloc */
653 old_size = _msize (old);
654 if (old_size >= new_size && old_size < new_size + 4) return old;
655 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
658 show_line("BEFORE REALLOC: \n", 0);
660 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
664 mnew = _expand (old, new_size); /* first try and expand in place */
667 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
668 mnew, new_size, old, old_size);
669 show_line(log_line, 0);
673 /* *********************************************************************** */
674 /* do this if you want to call the real realloc next - */
675 mnew = realloc (old, new_size);
678 show_line("AFTER REALLOC: \n", 0);
680 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
684 if (mnew != NULL) return mnew;
685 /* we are screwed typically if we ever drop through here - no more space */
686 /* *********************************************************************** */
687 mnew = malloc (new_size); /* otherwise find new space */
688 if (mnew == NULL) return mnew; /* if unable to allocate */
689 if (old_size < new_size) overlap = old_size;
690 else overlap = new_size;
691 memcpy (mnew, old, overlap); /* copy old data to new area */
692 free(old); /* free the old area */
697 void memory_error (char *s, int n)
700 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
701 show_maximums(log_file);
703 if (heap_flag) (void) heap_dump(log_file, 1);
706 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
707 show_line(log_line, 1);
708 show_maximums(stderr);
710 if (heap_flag) (void) heap_dump(stderr, 1);
712 /* exit (1); */ /* 94/Jan/22 */
713 /* return to let TeX do its thing (such as complain about runaway) */
714 /* don't set abort_flag here */
717 void trace_memory (char *s, int n)
719 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
720 show_line(log_line, 0);
723 void update_statistics (int address, int size, int oldsize)
725 if (address + size > max_address) max_address = address + size;
726 total_allocated = total_allocated + size - oldsize;
729 void probe_memory (void)
732 s = (char *) malloc (4); /* get current top address */
734 update_statistics ((int) s, 0, 0); /* show where we are */
737 void probe_show (void)
740 show_maximums(stdout);
742 if (heap_flag) (void) heap_dump(stdout, 1);
746 size_t roundup (size_t n)
748 if ((n % 4) == 0) return n;
749 else return ((n / 4) + 1) * 4;
753 /* using allocating hyphenation trie slows things down maybe 1% */
754 /* but saves typically (270k - 55k) = 215k of memory */
755 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
756 /* since hyphenation trie cannot be extended (after iniTeX) */
757 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
759 /* NOTE: we don't ever reallocate these */
760 /* returns -1 if it fails */
762 int allocate_tries (int trie_max)
765 /* if (trie_max > trie_size) {
766 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
767 trie_max, trie_size);
768 show_line(log_line, 1);
770 } */ /* ??? removed 1993/dec/17 */
771 if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
772 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
773 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
774 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
775 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
777 if (trace_flag) trace_memory("hyphen trie", n);
778 trie_trl = (halfword *) malloc (roundup(nl));
779 trie_tro = (halfword *) malloc (roundup(no));
780 trie_trc = (quarterword *) malloc (roundup(nc));
781 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL) {
782 memory_error("hyphen trie", n);
786 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
787 show_line(log_line, 0);
789 update_statistics ((int) trie_trl, nl, 0);
790 update_statistics ((int) trie_tro, no, 0);
791 update_statistics ((int) trie_trc, nc, 0);
792 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
793 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
795 probe_show(); /* 94/Mar/25 */
800 #ifdef ALLOCATEHYPHEN
801 bool prime (int); /* test function later in this file */
803 int current_prime = 0; /* remember in case reallocated later */
805 /* we don't return an address here, since TWO memory regions allocated */
806 /* plus, we don't really reallocate, we FLUSH the old information totally */
807 /* returns -1 if it fails */
809 int realloc_hyphen (int hyphen_prime)
812 if (!prime(hyphen_prime)) {
813 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
814 show_line(log_line, 1);
818 /* need not/cannot preserve old contents when hyphen prime is changed */
819 /* if (hyph_list != NULL) free(hyph_list); */
820 /* if (hyph_word != NULL) free(hyph_word); */
821 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
822 nw = (hyphen_prime + 1) * sizeof(str_number);
823 nl = (hyphen_prime + 1) * sizeof(halfword);
825 if (trace_flag) trace_memory("hyphen exception", n);
826 /* initially hyph_word will be NULL so this acts like malloc */
827 /* hyph_word = (str_number *) malloc (nw); */
828 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
829 /* initially hyph_list will be NULL so this acts like malloc */
830 /* hyph_list = (halfword *) malloc (nl); */
831 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
832 if (hyph_word == NULL || hyph_list == NULL) {
833 memory_error("hyphen exception", n);
837 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
838 show_line(log_line, 0);
840 /* cannot preserve old contents when hyphen prime is changed */
842 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
844 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
847 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
849 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
851 hyph_count = 0; /* or use reset_hyphen() in itex.c */
852 if (current_prime != 0) {
853 update_statistics ((int) hyph_word, nw,
854 (current_prime + 1) * sizeof(str_number));
855 update_statistics ((int) hyph_list, nl,
856 (current_prime + 1) * sizeof(halfword));
859 update_statistics ((int) hyph_word, nw, 0);
860 update_statistics ((int) hyph_list, nl, 0);
862 current_prime = hyphen_prime;
863 if (trace_flag) probe_show(); /* 94/Mar/25 */
868 int current_mem_size=0; /* current total words in main mem allocated -1 */
870 /* this gets called from itex.c when it figures out what mem_top is */
871 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
872 /* initial allocation only, may get expanded later */
873 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
874 /* returns NULL if it fails */
877 /* initial main memory alloc - mem_top */
878 memory_word *allocate_main_memory (int size)
882 /* Using -i *and* pre-loading format */ /* in this case get called twice */
883 /* Get rid of initial blank memory again or use realloc ... */
884 /* Could we avoid this by detecting presence of & before allocating ? */
885 /* Also, if its already large enough, maybe we can avoid this ? */
886 /* don't bother if current_mem_size == mem_max - mem_start ? */
887 if (mainmemory != NULL) {
888 /* free(mainmemory); */
889 /* mainmemory = NULL; */
890 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
891 /* if (mem_spec_flag)
892 show_line("Cannot change initial main memory size when format is read\n", 1);*/
895 mem_top = mem_bot + size;
896 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
897 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
900 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
901 if (mem_extra_low != 0 && !is_initex)
902 mem_start = mem_bot - mem_extra_low; /* increase main memory */
904 mem_start = 0; /* bottom of memory allocated by system */
905 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
906 mem_min = 0; /* bottom of area made available to TeX */
907 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
908 if (trace_flag) trace_memory("main memory", n);
909 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
910 /* normally mainmemory == NULL here so acts like malloc ... */
911 mainmemory = (memory_word *) REALLOC (mainmemory, n);
912 if (mainmemory == NULL) {
913 memory_error("initial main memory", n);
914 // exit (1); /* serious error */
918 sprintf(log_line, "Address main memory == %d\n", mainmemory);
919 show_line(log_line, 0);
922 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
924 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
925 show_line(log_line, 0);
927 update_statistics ((int) mainmemory, n,
928 (current_mem_size + 1) * sizeof (memory_word));
929 /* current_mem_size = (mem_max - mem_start + 1); */
930 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
931 if (trace_flag) probe_show(); /* 94/Mar/25 */
932 return zzzaa; /* same as zmem, mem 94/Jan/24 */
934 #endif /* end of ALLOCATEMAIN */
937 /* int firstallocation = 1; */
939 /* increase main memory allocation at low end and high end */
940 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
941 /* returns NULL if it fails */
943 memory_word *realloc_main (int losize, int hisize)
946 int newsize = 0; /* to quieten compiler */
947 int n = 0; /* to quieten compiler */
948 memory_word * newmemory = NULL; /* to quieten compiler */
950 /* if (losize == 0 && hisize > 0) runawayflag = 1;
951 else runawayflag = 0; */ /* 94/Jan/22 */
954 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
955 show_line(log_line, 0);
958 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
960 show_line("Please use `-m=...' on command line\n", 0);
961 // abort_flag++; // ???
965 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
966 show_line(log_line, 0);
968 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
969 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
970 // abort_flag++; // ???
973 /* first allocation should expand *both* lo and hi */
974 if (hisize == 0 && mem_end == mem_max) hisize = losize;
975 if (losize == 0 && mem_start == mem_min) losize = hisize;
976 /* try and prevent excessive frequent reallocations */
977 /* while avoiding over allocation by too much */
978 minsize = current_mem_size / 100 * percent_grow;
979 if (losize + hisize < minsize) {
980 if (losize > 0 && hisize > 0) {
981 losize = minsize / 2;
982 hisize = minsize / 2;
984 else if (losize > 0) losize = minsize;
985 else if (hisize > 0) hisize = minsize;
987 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
988 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
990 for (k = 0; k < MAXSPLITS; k++) {
991 newsize = current_mem_size + losize + hisize;
992 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
993 while (newsize >= max_mem_size) {
994 losize = losize / 2; hisize = hisize / 2;
995 newsize = current_mem_size + losize + hisize;
998 n = (newsize + 1) * sizeof (memory_word);
999 if (trace_flag) trace_memory("main memory", n);
1000 newmemory = (memory_word *) REALLOC (mainmemory, n);
1001 if (newmemory != NULL) break; /* did we get it ? */
1002 if (current_mem_size == 0) break; /* in case we ever use for initial */
1003 losize = losize / 2; hisize = hisize / 2;
1006 if (newmemory == NULL) {
1007 memory_error("main memory", n);
1008 return zzzaa; /* try and continue with TeX !!! */
1011 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1012 show_line(log_line, 0);
1015 /* shift everything upward to make space for new low area */
1017 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1018 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1019 show_line(log_line, 0);
1021 memmove (newmemory + losize, newmemory,
1022 /* current_mem_size * sizeof(memory_word)); */
1023 (current_mem_size + 1) * sizeof(memory_word));
1024 /* could reduce words moved by (mem_max - mem_end) */
1026 mainmemory = newmemory; /* remember for free later */
1027 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1028 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1029 update_statistics ((int) mainmemory, n,
1030 (current_mem_size + 1) * sizeof (memory_word));
1031 current_mem_size = newsize;
1032 if (current_mem_size != mem_max - mem_start) {
1033 show_line("ERROR: Impossible Memory Error\n", 1);
1035 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1036 else zzzaa = mainmemory;
1037 if (trace_flag) probe_show(); /* 94/Mar/25 */
1043 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1045 int current_font_mem_size=0;
1047 /* fmemoryword can be either halfword or memory_word */
1048 fmemoryword *realloc_font_info (int size)
1049 { /* number of memorywords */
1050 fmemoryword *newfontinfo=NULL;
1052 int newsize=0; /* to quieten compiler */
1053 int n=0; /* to quieten compiler */
1056 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1057 show_line(log_line, 0);
1059 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1060 /* during initial allocation current_font_mem_size == 0 */
1061 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1062 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1063 return font_info; /* pass it back to TeX 99/Fabe/4 */
1065 /* try and prevent excessive frequent reallocations */
1066 /* while avoiding over allocation by too much */
1067 /* minsize = current_font_mem_size / 2; */
1068 minsize = current_font_mem_size / 100 * percent_grow;
1069 if (size < minsize) size = minsize;
1070 if (size < initial_font_mem_size) size = initial_font_mem_size;
1072 for (k=0; k < MAXSPLITS; k++) {
1073 newsize = current_font_mem_size + size;
1074 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1075 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1076 n = (newsize + 1) * sizeof (fmemoryword);
1077 if (trace_flag) trace_memory("font_info", n);
1078 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1079 if (newfontinfo != NULL) break; /* did we get it ? */
1080 if (current_font_mem_size == 0) break; /* initial allocation must work */
1084 if (newfontinfo == NULL) {
1085 memory_error("font", n);
1086 return font_info; /* try and continue !!! */
1088 font_info = newfontinfo;
1090 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1091 show_line(log_line, 0);
1093 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1094 current_font_mem_size = newsize;
1095 if (trace_flag) probe_show(); /* 94/Mar/25 */
1100 #ifdef ALLOCATESTRING
1101 int current_pool_size=0;
1103 packed_ASCII_code *realloc_str_pool (int size)
1108 packed_ASCII_code *newstrpool=NULL;
1111 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1112 show_line(log_line, 0);
1114 if (current_pool_size == pool_size) {
1115 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1117 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1119 /* minsize = current_pool_size / 2; */
1120 minsize = current_pool_size / 100 * percent_grow;
1121 if (size < minsize) size = minsize;
1122 if (size < initial_pool_size) size = initial_pool_size;
1124 for (k = 0; k < MAXSPLITS; k++) {
1125 newsize = current_pool_size + size;
1126 if (newsize > pool_size) newsize = pool_size;
1127 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1128 n = (newsize + 1) * sizeof (packed_ASCII_code);
1129 if (trace_flag) trace_memory("str_pool", n);
1130 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1131 if (newstrpool != NULL) break; /* did we get it ? */
1132 if (current_pool_size == 0) break; /* initial allocation must work */
1133 size = size / 2; /* else can retry smaller */
1136 if (newstrpool == NULL) {
1137 memory_error("string pool", n);
1138 return str_pool; /* try and continue !!! */
1140 str_pool = newstrpool;
1141 update_statistics ((int) str_pool, n, current_pool_size);
1142 current_pool_size = newsize;
1144 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1145 show_line(log_line, 0);
1147 if (trace_flag) probe_show(); /* 94/Mar/25 */
1152 #ifdef ALLOCATESTRING
1153 int current_max_strings=0;
1155 pool_pointer *realloc_str_start (int size)
1160 pool_pointer *newstrstart=NULL;
1163 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1164 show_line(log_line, 0);
1166 if (current_max_strings == max_strings) {
1167 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1169 return str_start; /* pass it back to TeX 99/Fabe/4 */
1171 /* minsize = current_max_strings / 2; */
1172 minsize = current_max_strings / 100 * percent_grow;
1173 if (size < minsize) size = minsize;
1174 if (size < initial_max_strings) size = initial_max_strings;
1176 for (k = 0; k < MAXSPLITS; k++) {
1177 newsize = current_max_strings + size;
1178 if (newsize > max_strings) newsize = max_strings;
1179 /* important + 1 since str_start[maxstring + 1] originally */
1180 n = (newsize + 1) * sizeof (pool_pointer);
1181 if (trace_flag) trace_memory("str_start", n);
1182 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1183 if (newstrstart != NULL) break; /* did we get it ? */
1184 if (current_max_strings == 0) break; /* initial allocation must work */
1185 size = size / 2; /* otherwise can try smaller */
1188 if (newstrstart == NULL) {
1189 memory_error("string pointer", n);
1190 return str_start; /* try and continue */
1192 str_start = newstrstart;
1193 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1194 current_max_strings = newsize;
1196 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1197 show_line(log_line, 0);
1199 if (trace_flag) probe_show(); /* 94/Mar/25 */
1206 /* returns -1 if it fails */
1208 int allocate_ini (int size)
1209 { /* size == trie_size */
1210 int n, nl, no, nc, nr, nh, nt;
1211 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1212 no = (size + 1) * sizeof(trie_op_code);
1213 nc = (size + 1) * sizeof(packed_ASCII_code);
1214 /* nt = (size + 1) * sizeof(bool); */
1215 nt = (size + 1) * sizeof(char);
1216 n = nl + no + nc + nr + nh + nt;
1217 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1218 3 * sizeof(trie_pointer) + sizeof (char)); */
1219 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1220 trie_l = (trie_pointer *) malloc (roundup(nl));
1221 trie_o = (trie_op_code *) malloc (roundup(no));
1222 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1223 trie_r = (trie_pointer *) malloc (roundup(nr));
1224 trie_hash = (trie_pointer *) malloc (roundup(nh));
1225 /* trie_taken = (bool *) malloc (nt); */
1226 trie_taken = (char *) malloc (roundup(nt));
1227 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1228 trie_hash == NULL || trie_taken == NULL) {
1229 memory_error("iniTeX hyphen trie", n);
1230 // exit (1); /* serious error */
1234 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1235 trie_l, trie_o, trie_c);
1236 show_line(log_line, 0);
1237 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1238 trie_r, trie_hash, trie_taken);
1239 show_line(log_line, 0);
1241 update_statistics ((int) trie_l, nl, 0);
1242 update_statistics ((int) trie_o, no, 0);
1243 update_statistics ((int) trie_c, nc, 0);
1244 update_statistics ((int) trie_r, nr, 0);
1245 update_statistics ((int) trie_hash, nh, 0);
1246 update_statistics ((int) trie_taken, nt, 0);
1247 /* trie_size = size; */ /* ??? */
1248 if (trace_flag) probe_show(); /* 94/Mar/25 */
1249 return 0; // success
1253 #ifdef ALLOCATESAVESTACK
1254 int current_save_size=0;
1256 memory_word *realloc_save_stack (int size)
1260 memory_word *newsave_stack=NULL;
1263 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1264 show_line(log_line, 0);
1266 if (current_save_size == save_size) { /* arbitrary limit */
1267 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1269 return save_stack; /* let TeX handle the error */
1271 minsize = current_save_size / 100 * percent_grow;
1272 if (size < minsize) size = minsize;
1273 if (size < initial_save_size) size = initial_save_size;
1275 for (k = 0; k < MAXSPLITS; k++) {
1276 newsize = current_save_size + size;
1277 if (newsize > save_size) newsize = save_size;
1278 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1279 if (trace_flag) trace_memory("save_stack", n);
1280 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1281 if (newsave_stack != NULL) break; /* did we get it ? */
1282 if (current_save_size == 0) break; /* initial allocation must work */
1283 size = size / 2; /* else can retry smaller */
1286 if (newsave_stack == NULL) {
1287 memory_error("save stack", n);
1288 return save_stack; /* try and continue !!! */
1290 save_stack = newsave_stack;
1291 update_statistics ((int) save_stack, n, current_save_size);
1292 current_save_size = newsize;
1294 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1295 show_line(log_line, 0);
1296 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1297 show_line(log_line, 0);
1299 if (trace_flag) probe_show(); /* 94/Mar/25 */
1304 #ifdef ALLOCATEINPUTSTACK
1305 int current_stack_size=0; /* input stack size */
1307 in_state_record *realloc_input_stack (int size)
1311 in_state_record *newinputstack=NULL;
1314 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1315 show_line(log_line, 0);
1317 if (current_stack_size == stack_size) { /* arbitrary limit */
1318 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1322 minsize = current_stack_size / 100 * percent_grow;
1323 if (size < minsize) size = minsize;
1324 if (size < initial_stack_size) size = initial_stack_size;
1326 for (k = 0; k < MAXSPLITS; k++) {
1327 newsize = current_stack_size + size;
1328 if (newsize > stack_size) newsize = stack_size;
1329 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1330 if (trace_flag) trace_memory("input_stack", n);
1331 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1332 if (newinputstack != NULL) break; /* did we get it ? */
1333 if (current_stack_size == 0) break; /* initial allocation must work */
1334 size = size / 2; /* else can retry smaller */
1337 if (newinputstack == NULL) {
1338 memory_error("input stack", n);
1339 return input_stack; /* try and continue !!! */
1341 input_stack = newinputstack;
1342 update_statistics ((int) input_stack, n, current_stack_size);
1343 current_stack_size = newsize;
1345 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1346 show_line(log_line, 0);
1347 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1348 show_line(log_line, 0);
1350 if (trace_flag) probe_show(); /* 94/Mar/25 */
1355 #ifdef ALLOCATENESTSTACK
1356 int current_nest_size=0; /* current nest size */
1358 list_state_record *realloc_nest_stack (int size)
1362 list_state_record *newnest=NULL;
1365 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1366 show_line(log_line, 0);
1368 if (current_nest_size == nest_size) { /* arbitrary limit */
1369 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1371 return nest; /* let TeX handle the error */
1373 minsize = current_nest_size / 100 * percent_grow;
1374 if (size < minsize) size = minsize;
1375 if (size < initial_nest_size) size = initial_nest_size;
1377 for (k = 0; k < MAXSPLITS; k++) {
1378 newsize = current_nest_size + size;
1379 if (newsize > nest_size) newsize = nest_size;
1380 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1381 if (trace_flag) trace_memory("nest stack", n);
1382 newnest = (list_state_record *) REALLOC (nest, n);
1383 if (newnest != NULL) break; /* did we get it ? */
1384 if (current_nest_size == 0) break; /* initial allocation must work */
1385 size = size / 2; /* else can retry smaller */
1388 if (newnest == NULL) {
1389 memory_error("nest stack", n);
1390 return nest; /* try and continue !!! */
1393 update_statistics ((int) nest, n, current_nest_size);
1394 current_nest_size = newsize;
1396 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1397 show_line(log_line, 0);
1398 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1399 show_line(log_line, 0);
1401 if (trace_flag) probe_show(); /* 94/Mar/25 */
1406 #ifdef ALLOCATEPARAMSTACK
1407 int current_param_size=0; /* current param size */
1409 halfword *realloc_param_stack (int size)
1413 halfword *newparam=NULL;
1416 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1417 show_line(log_line, 0);
1419 if (current_param_size == param_size) { /* arbitrary limit */
1420 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1422 return param_stack; /* let TeX handle the error */
1424 minsize = current_param_size / 100 * percent_grow;
1425 if (size < minsize) size = minsize;
1426 if (size < initial_param_size) size = initial_param_size;
1428 for (k = 0; k < MAXSPLITS; k++) {
1429 newsize = current_param_size + size;
1430 if (newsize > param_size) newsize = param_size;
1431 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1432 if (trace_flag) trace_memory("param stack", n);
1433 newparam = (halfword *) REALLOC (param_stack, n);
1434 if (newparam != NULL) break; /* did we get it ? */
1435 if (current_param_size == 0) break; /* initial allocation must work */
1436 size = size / 2; /* else can retry smaller */
1439 if (newparam == NULL) {
1440 memory_error("param stack", n);
1441 return param_stack; /* try and continue !!! */
1443 param_stack = newparam;
1444 update_statistics ((int) param_stack, n, current_param_size);
1445 current_param_size = newsize;
1447 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1448 show_line(log_line, 0);
1449 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1450 show_line(log_line, 0);
1452 if (trace_flag) probe_show(); /* 94/Mar/25 */
1457 #ifdef ALLOCATEBUFFER
1458 int current_buf_size=0;
1460 ASCII_code *realloc_buffer (int size)
1464 ASCII_code *newbuffer=NULL;
1467 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1468 show_line(log_line, 0);
1470 if (current_buf_size == buf_size) { /* arbitrary limit */
1471 /* memory_error ("buffer", buf_size); */
1473 return buffer; /* pass it back to TeX 99/Fabe/4 */
1475 minsize = current_buf_size / 100 * percent_grow;
1476 if (size < minsize) size = minsize;
1477 if (size < initial_buf_size) size = initial_buf_size;
1479 for (k = 0; k < MAXSPLITS; k++) {
1480 newsize = current_buf_size + size;
1481 if (newsize > buf_size) newsize = buf_size;
1482 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1483 if (trace_flag) trace_memory("buffer", n);
1484 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1485 if (newbuffer != NULL) break; /* did we get it ? */
1486 if (current_buf_size == 0) break; /* initial allocation must work */
1487 size = size / 2; /* else can retry smaller */
1490 if (newbuffer == NULL) {
1491 memory_error("buffer", n);
1492 return buffer; /* try and continue !!! */
1495 update_statistics ((int) buffer, n, current_buf_size);
1497 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1499 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1501 current_buf_size = newsize;
1503 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1504 show_line(log_line, 0);
1505 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1506 show_line(log_line, 0);
1508 if (trace_flag) probe_show(); /* 94/Mar/25 */
1513 /* we used to allocate this one only to reduce the size of the PE file */
1514 /* not used anymore - NO advantage */
1516 #ifdef ALLOCATEDVIBUF
1517 eight_bits *allocatedvibuf (int size)
1519 eight_bits *dvi_buf;
1522 n = (size + 1) * sizeof(eight_bits);
1523 if (trace_flag) trace_memory("dvi_buf", n);
1524 dvi_buf = (eight_bits *) malloc (roundup(n));
1525 if (dvi_buf == NULL) {
1526 memory_error("dvi_buf", n);
1530 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1531 show_line(log_line, 0);
1533 update_statistics ((int) dvi_buf, n, 0);
1534 if (trace_flag) probe_show(); /* 94/Mar/25 */
1539 /* we used to allocate this one only to reduce the size of the PE file */
1540 /* it can be done without loss in performance, since register eqtb = zeqtb */
1541 #ifdef ALLOCATEZEQTB
1542 memory_word *allocatezeqtb (int k)
1547 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1548 if (trace_flag) trace_memory("eqtb", n);
1549 zeqtb = (memory_word *) malloc (roundup(n));
1550 if (zeqtb == NULL) {
1551 memory_error("eqtb", n);
1552 // exit (1); /* serious error */
1556 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1557 show_line(log_line, 0);
1559 update_statistics ((int) zeqtb, n, 0);
1560 if (trace_flag) probe_show(); /* 94/Mar/25 */
1565 /* here is the main memory allocation routine -- calls the above */
1566 /* returns -1 if it fails */
1568 int allocate_memory (void)
1569 { /* allocate rather than static 93/Nov/26 */
1572 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1576 #error ERROR: Not ready for ALLOCATEHASH...
1579 /* probably not worth while/not a good idea allocating following */
1580 /* they are all rather small, and typically don't need expansion */
1581 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1583 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1584 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1585 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1587 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1589 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1591 if (trace_flag) trace_memory("hash table", n);
1593 zzzae = (htwohalves *) malloc (roundup(n));
1595 zzzae = (twohalves *) malloc (roundup(n));
1597 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1598 if (zzzae == NULL) {
1599 memory_error("hash table", n);
1600 // exit (1); /* serious error */
1601 return -1; /* serious error */
1604 n = (inputsize + 1) * sizeof(memory_word);
1605 if (trace_flag) trace_memory("input_stack", n);
1606 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1607 input_stack = (memory_word *) malloc (roundup(n));
1608 if (input_stack == NULL) {
1609 memory_error("input_stack", n);
1610 // exit (1); /* serious error */
1611 return -1; /* serious error */
1615 /* no real reason to allocate dvi_buf - no need to ever grow it */
1616 #ifdef ALLOCATEDVIBUF
1617 /* zdvibuf = NULL; */
1618 zdvibuf = allocatedvibuf (dvi_buf_size);
1619 if (zdvibuf == NULL) return -1;
1622 #ifdef ALLOCATEZEQTB
1624 #ifdef INCREASEFONTS
1625 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1626 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1628 /* zeqtb = allocatezeqtb (13507); */
1629 zeqtb = allocatezeqtb (hash_size + 4007);
1633 #ifdef ALLOCATEINPUTSTACK
1634 input_stack = NULL; /* new 1999/Jan/21 */
1635 current_stack_size = 0;
1636 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1639 #ifdef ALLOCATENESTSTACK
1640 nest = NULL; /* new 1999/Jan/21 */
1641 current_nest_size = 0;
1642 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1645 #ifdef ALLOCATEPARAMSTACK
1646 param_stack = NULL; /* new 1999/Jan/21 */
1647 current_param_size = 0;
1648 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1651 #ifdef ALLOCATESAVESTACK
1652 save_stack = NULL; /* new 1999/Jan/7 */
1653 current_save_size = 0;
1654 save_stack = realloc_save_stack (initial_save_size);
1658 buffer = NULL; /* need to do earlier */
1659 current_buf_size = 0;
1660 buffer = realloc_buffer (initial_buf_size);
1663 #ifdef ALLOCATESTRING
1665 current_pool_size = 0;
1667 current_max_strings = 0;
1668 /* need to create space because iniTeX writes in before reading pool file */
1669 /* for a start, puts in strings for 256 characters */
1670 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1672 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1673 str_pool = realloc_str_pool (initial_pool_size);
1674 str_start = realloc_str_start (initial_max_strings);
1678 /* the following can save a lot of the usual 800k fixed allocation */
1681 current_font_mem_size = 0;
1682 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1683 /* if ini-TeX we need to do it here - no format file read later */
1684 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1690 mem_min = mem_bot; /* just to avoid complaints in texbody */
1691 mem_top = mem_initex;
1693 /* allocate main memory here if this is iniTeX */
1694 /* otherwise wait for format undumping in itex.c ... */
1696 /* avoid this if format specified on command line ??? */
1697 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1698 mem = allocate_main_memory(mem_initex); /* made variable ! */
1701 return -1; /* serious error */
1705 /* now for the hyphenation exception stuff */
1706 #ifdef ALLOCATEHYPHEN
1709 /* this will be overridden later by what is in format file */
1710 hyphen_prime = default_hyphen_prime;
1711 /* non ini-TeX use assumes format will be read and that specifies size */
1713 if (new_hyphen_prime) hyphen_prime = new_hyphen_prime;
1714 if (realloc_hyphen (hyphen_prime)) /* allocate just in case no format */
1719 /* now for memory for the part of the hyphenation stuff that always needed */
1720 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1721 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1722 #ifdef ALLOCATETRIES
1724 if (allocate_tries (trie_size)) return -1;
1728 /* now for memory for hyphenation stuff needed only when running iniTeX */
1731 if (allocate_ini(trie_size)) return -1;
1734 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1735 trie_c = NULL; /* (trie_size + 1) * char */
1736 trie_taken = NULL; /* (trie_size + 1) * bool */
1740 free(holeadr); /* create the hole */
1742 return 0; // success
1745 /* returns non-zero if error - done to test integrity of stack mostly */
1747 int free_memory (void)
1748 { /* free in reverse order 93/Nov/26 */
1750 unsigned heaptotal=0;
1751 /* unsigned total; */
1753 if (trace_flag) show_line("free_memory ", 0);
1756 if (debug_flag) check_eqtb("free_memory");
1758 if (verbose_flag || trace_flag) show_maximums(stdout);
1760 if (heap_flag) (void) heap_dump(stdout, 1);
1764 heaptotal = (void) heap_dump(stdout, 0);
1766 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1767 heaptotal, max_address);
1768 show_line(log_line, 0);
1771 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1772 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1773 show_line(log_line, 0);
1775 /* following only needed to check consistency of heap ... useful debugging */
1776 if (trace_flag) show_line("Freeing memory again\n", 0);
1779 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1781 /* the following checks the heap integrity */
1783 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1785 #ifdef SHOWHEAPERROR
1787 if (n != _HEAPOK) { /* 94/Feb/18 */
1788 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1789 show_line(log_line, 1);
1790 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1791 show_line(log_line, 0);
1792 return n; /* non-zero and negative */ /* unreachable ??? */
1795 /* only free memory if safe ... additional check */
1798 if (trie_taken != NULL) free(trie_taken);
1799 if (trie_hash != NULL) free(trie_hash);
1800 if (trie_r != NULL) free(trie_r);
1801 if (trie_c != NULL) free(trie_c);
1802 if (trie_o != NULL) free(trie_o);
1803 if (trie_l != NULL) free(trie_l);
1805 trie_hash = trie_l = trie_r = NULL;
1810 #ifdef ALLOCATETRIES
1811 if (trie_trc != NULL) free (trie_trc);
1812 if (trie_tro != NULL) free (trie_tro);
1813 if (trie_trl != NULL) free (trie_trl);
1815 trie_tro = trie_trl = NULL;
1817 #ifdef ALLOCATEHYPHEN
1818 if (hyph_list != NULL) free(hyph_list);
1819 if (hyph_word != NULL) free(hyph_word);
1824 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1825 if (mainmemory != NULL) free(mainmemory);
1829 if (font_info != NULL) free(font_info);
1832 #ifdef ALLOCATESTRING
1833 if (str_start != NULL) free(str_start);
1834 if (str_pool != NULL) free(str_pool);
1840 if (zzzae != NULL) free(zzzae);
1844 #ifdef ALLOCATEDVIBUF
1845 if (zdvibuf != NULL) free(zdvibuf);
1848 #ifdef ALLOCATEZEQTB
1849 if (zeqtb != NULL) free(zeqtb);
1853 #ifdef ALLOCATEPARAMSTACK
1854 if (param_stack != NULL) free(param_stack);
1857 #ifdef ALLOCATENESTSTACK
1858 if (nest != NULL) free(nest);
1861 #ifdef ALLOCATEINPUTSTACK
1862 if (input_stack != NULL) free(input_stack);
1865 #ifdef ALLOCATESAVESTACK
1866 if (save_stack != NULL) free(save_stack);
1869 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1870 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1871 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1872 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1873 format_file = string_file = source_direct = NULL;
1874 if (dvi_file_name != NULL) free(dvi_file_name);
1875 if (log_file_name != NULL) free(log_file_name);
1876 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1883 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1884 if (x % 2 == 0) return false;
1885 for (k = 3; k < x; k = k + 2) {
1886 if (x % k == 0) return false;
1887 /* if (k * k > x) return true; */
1888 if (sum * 4 > x) return true;
1895 bool show_use=false;
1896 bool floating=false;
1898 void complainarg (int c, char *s)
1900 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1901 show_line(log_line, 1);
1902 show_use = 1; // 2000 June 21
1905 /* following is list of allowed command line flags and args */
1907 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1909 /* only 01234567.9 still left to take ... maybe recycle u */
1911 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1913 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1915 void reorderargs (int ac, char **av)
1916 { /* put in 1993/Dec/28 */
1919 // char takeargs[128]; /* large enough for all command line arg chars */
1920 char takeargs[256]; /* large enough for all command line arg chars */
1922 /* assumes arg pointers av[] are writeable */
1923 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1925 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1926 /* show_line("No arguments?\n", 0); */ /* debugging */
1927 return; /* no args ! */
1931 t = takeargs; /* list of those that take args */
1932 while (*s != '\0' && *(s+1) != '\0') {
1933 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1938 show_line(takeargs, 0);
1943 for (;;) { /* scan to end of command line args */
1944 if (*av[n] != '-') break;
1945 /* does it take an argument ? and is this argument next ? */
1947 *(av[n]+2) == '\0' &&
1948 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1949 strchr(takeargs, *(av[n]+1)) != NULL)
1950 n += 2; /* step over it */
1955 for (;;) { /* look for more command line args */
1958 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
1959 while (m < ac && *av[m] != '-') m++; /* first command */
1961 /* does it take an argument ? and is this argument next ? */
1962 /* check first whether the `-x' is isolated, or arg follows directly */
1963 /* then check whether this is one of those that takes an argument */
1965 *(av[m]+2) == '\0' &&
1966 strchr(takeargs, *(av[m]+1)) != NULL) {
1967 s = av[m]; /* move command down before non-command */
1969 for (; m > n; m--) av[m+1] = av[m-1];
1972 n += 2; /* step over moved args */
1975 s = av[m]; /* move command down before non-command */
1976 for (; m > n; m--) av[m] = av[m-1];
1978 n++; /* step over moved args */
1983 int test_align (int address, int size, char *name)
1986 if (size > 4) n = address % 4;
1987 else n = address % size;
1989 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
1990 show_line(log_line, 0);
1995 /* activate detailed checking of alignment when trace_flag is set */
1997 void check_fixed_align (int flag)
1999 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2000 show_line("PLEASE RECOMPILE ME!\n", 1);
2002 #ifdef CHECKALIGNMENT
2004 test_align ((int) &mem_top, 4, "mem_top");
2005 test_align ((int) &mem_max, 4, "mem_max");
2006 test_align ((int) &mem_min, 4, "mem_min");
2007 test_align ((int) &bad, 4, "bad");
2008 test_align ((int) &trie_size, 4, "trie_size");
2009 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2010 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2011 test_align ((int) &name_length, 4, "name_length");
2012 test_align ((int) &first, 4, "first");
2013 test_align ((int) &last, 4, "last");
2014 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2015 test_align ((int) &pool_ptr, 4, "pool_ptr");
2016 test_align ((int) &str_ptr, 4, "str_ptr");
2017 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2018 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2019 test_align ((int) &log_file, 4, "log_file");
2020 test_align ((int) &tally, 4, "tally");
2021 test_align ((int) &term_offset, 4, "term_offset");
2022 test_align ((int) &file_offset, 4, "file_offset");
2023 test_align ((int) &trick_count, 4, "trick_count");
2024 test_align ((int) &first_count, 4, "first_count");
2025 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2026 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2027 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2028 test_align ((int) &use_err_help, 4, "use_err_help");
2029 test_align ((int) &interrupt, 4, "interrupt");
2030 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2031 test_align ((int) &arith_error, 4, "arith_error");
2032 test_align ((int) &tex_remainder, 4, "tex_remainder");
2033 test_align ((int) &temp_ptr, 4, "temp_ptr");
2034 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2035 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2036 test_align ((int) &var_used, 4, "var_used");
2037 test_align ((int) &dyn_used, 4, "dyn_used");
2038 test_align ((int) &avail, 4, "avail");
2039 test_align ((int) &mem_end, 4, "mem_end");
2040 test_align ((int) &mem_start, 4, "mem_start");
2041 test_align ((int) &rover, 4, "rover");
2042 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2043 test_align ((int) &depth_threshold, 4, "depth_threshold");
2044 test_align ((int) &breadth_max, 4, "breadth_max");
2045 test_align ((int) &nest, sizeof(nest[0]), "nest");
2048 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2050 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2051 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2052 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2053 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2055 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2056 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2057 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2058 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2059 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2060 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2061 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2062 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2064 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2065 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2066 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2067 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2068 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2069 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2070 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2071 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2072 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2073 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2074 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2075 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2076 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2077 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2078 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2079 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2080 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2081 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2082 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2083 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2084 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2085 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2086 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2087 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2089 #ifdef ALLOCATEDVIBUF
2090 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2092 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2093 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2094 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2095 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2096 test_align ((int) &background, sizeof(background[0]), "background");
2097 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2098 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2099 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2100 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2101 test_align ((int) &hc, sizeof(hc[0]), "hc");
2102 test_align ((int) &hu, sizeof(hu[0]), "hu");
2103 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2104 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2106 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2107 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2108 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2109 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2111 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2112 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2113 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2114 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2115 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2117 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2118 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2119 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2120 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2124 void check_alloc_align (int flag) {
2125 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2126 show_line("PLEASE RECOMPILE ME!\n", 1);
2127 #ifdef CHECKALIGNMENT
2130 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2132 #ifndef ALLOCATEDVIBUF
2133 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2135 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2136 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2137 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2138 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2139 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2140 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2141 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2142 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2143 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2144 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2145 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2146 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2147 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2148 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2149 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2154 void showaddresses (void)
2158 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2159 show_line(log_line, 0);
2160 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2161 show_line(log_line, 0);
2162 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2163 show_line(log_line, 0);
2164 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2165 save_stack, input_stack, line_stack, param_stack);
2166 show_line(log_line, 0);
2167 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2168 font_check, font_size, font_dsize, font_params, font_name);
2169 show_line(log_line, 0);
2170 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2171 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2172 show_line(log_line, 0);
2176 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2178 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2179 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2181 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2182 bool backwardflag = false; /* don't cripple all advanced features */
2183 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2184 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2185 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2186 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2187 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2188 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2189 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2190 bool workingdirectory = false; /* if working directory set in ini */
2191 /* set up full file name for dviwindo.ini and check for [Environment] */
2193 bool setupdviwindo (void)
2194 { /* set up full file name for dviwindo.ini */
2195 char dviwindoini[PATH_MAX];
2196 char line[PATH_MAX];
2199 int em = strlen(envsection);
2200 int wm = strlen(wndsection);
2201 int dm = strlen(workdirect);
2205 /* Easy to find Windows directory if Windows runs */
2206 /* Or if user kindly set WINDIR environment variable */
2207 /* Or if running in Windows NT */
2208 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2209 (windir = getenv("WINDIR")) != NULL ||
2210 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2211 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2212 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2213 strcpy(dviwindoini, windir);
2214 strcat(dviwindoini, "\\");
2215 strcat(dviwindoini, inifilename);
2216 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2219 _searchenv (inifilename, "PATH", dviwindoini);
2220 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2223 wndflag = envflag = 0;
2224 /* workingdirectory = false; */
2225 if (*dviwindoini != '\0') {
2226 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2227 /* check whether dviwindo.ini actually has [Environment] section */
2228 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2229 else pinput = _fsopen(dviwindo, "r", share_flag);
2230 if (pinput != NULL) {
2231 while (fgets (line, sizeof(line), pinput) != NULL) {
2232 if (*line == ';') continue;
2233 if (*line == '\n') continue;
2235 if (wndflag && envflag) break; /* escape early */
2237 if (_strnicmp(line, wndsection, wm) == 0) {
2239 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2240 show_line(log_line, 0);
2244 else if (_strnicmp(line, envsection, em) == 0) {
2246 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2247 show_line(log_line, 0);
2249 /* fclose(input); */
2252 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2254 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2255 show_line(log_line, 0);
2257 workingdirectory = true;
2261 (void) fclose(pinput);
2265 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2266 (void) fclose(pinput);
2268 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2269 strcpy(dviwindo, ""); /* failed, for one reason or another */
2274 /* cache to prevent allocating twice in a row */
2276 char *lastname=NULL, *lastvalue=NULL;
2278 /* get value of env var - try first in dviwindo.ini then DOS env */
2279 /* returns allocated string -- these strings are not freed again */
2280 /* is it safe to do that now ? 98/Jan/31 */
2281 char *grabenv (char *varname)
2283 char line[PATH_MAX];
2287 /* int m = strlen(envsection); */
2288 /* int n = strlen(varname); */
2290 if (varname == NULL) return NULL; /* sanity check */
2291 if (*varname == '\0') return NULL; /* sanity check */
2292 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2293 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2294 if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2296 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2297 show_line(log_line, 0);
2299 /* return lastvalue; */ /* save some time here */
2300 return xstrdup(lastvalue);
2301 /* duplicate so can free safely 98/Jan/31 */
2304 /* hmm, following was not xstrdup(...) */ /* not cached */
2305 if (usedviwindo == 0 || *dviwindo == '\0') {
2306 /* return getenv(varname); */
2307 s = getenv(varname);
2308 if (s == NULL) return NULL;
2309 else return xstrdup(s); /* make safe 98/Jan/31 */
2312 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2313 else pinput = _fsopen(dviwindo, "r", share_flag);
2315 if (pinput != NULL) {
2316 m = strlen(envsection);
2317 /* search for [Environment] section */ /* should be case insensitive */
2318 while (fgets (line, sizeof(line), pinput) != NULL) {
2319 if (*line == ';') continue;
2320 if (*line == '\n') continue;
2321 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2322 /* search for varname=... */ /* should be case sensitive ? */
2323 n = strlen(varname);
2324 while (fgets (line, sizeof(line), pinput) != NULL) {
2325 if (*line == ';') continue;
2326 if (*line == '[') break;
2327 /* if (*line == '\n') break; */ /* ??? */
2328 if (*line <= ' ') continue; /* 95/June/23 */
2329 /* if (strncmp(line, varname, n) == 0 && */
2330 if (_strnicmp(line, varname, n) == 0 &&
2331 *(line+n) == '=') { /* found it ? */
2332 (void) fclose (pinput);
2333 /* flush trailing white space */
2334 s = line + strlen(line) - 1;
2335 while (*s <= ' ' && s > line) *s-- = '\0';
2336 if (trace_flag) { /* DEBUGGING ONLY */
2337 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2338 show_line(log_line, 0);
2341 if (lastname != NULL) free(lastname);
2342 lastname = xstrdup (varname);
2343 if (lastvalue != NULL) free(lastvalue);
2344 lastvalue = xstrdup(s);
2345 return xstrdup(s); /* 98/Jan/31 */
2346 } /* end of matching varname */
2347 } /* end of while fgets */
2348 /* break; */ /* ? not found in designated section */
2349 } /* end of search for [Environment] section */
2351 (void) fclose (pinput);
2352 } /* end of if fopen */
2353 s = getenv(varname); /* failed, so try and get from environment */
2354 /* if (s != NULL) return s; */
2356 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2357 if (lastname != NULL) free(lastname);
2358 lastname = xstrdup (varname);
2359 if (lastvalue != NULL) free(lastvalue);
2360 lastvalue = xstrdup(s); /* remember in case asked again ... */
2362 return xstrdup(s); /* 98/Jan/31 */
2364 else return NULL; /* return NULL if not found anywhere */
2367 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2369 void flush_trailing_slash (char *directory)
2372 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2373 if (strcmp(directory, "") != 0) {
2374 s = directory + strlen(directory) - 1;
2375 if (*s == '\\' || *s == '/') *s = '\0';
2379 void knuthify (void)
2381 /* show_current = false; */ /* show ultimate limits */
2382 /* reorder_arg_flag = false; */ /* don't reorder command line */
2383 /* deslash = false; */ /* don't unixify file names */
2384 /* return_flag = false; */ /* don't allow just ^^M termination */
2385 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2386 restrict_to_ascii = false; /* don't complain non ASCII */
2387 allow_patterns = false; /* don't allow pattern redefinition */
2388 show_in_hex = true; /* show character code in hex */
2389 show_in_dos = false; /* redundant with previous */
2390 show_numeric = false; /* don't show character code decimal */
2391 show_missing = false; /* don't show missing characters */
2392 civilize_flag = false; /* don't reorder date fields */
2393 c_style_flag = false; /* don't add file name to error msg */
2394 show_fmt_flag = false; /* don't show format file in log */
2395 show_tfm_flag = false; /* don't show metric file in log */
2396 /* font_max = 255; */ /* revert to TeX 82 limit */
2397 /* if you want this, change in tex.h definition of font_max to `int' */
2398 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2400 show_line_break_stats = false; /* do not show line break stats */
2401 show_fonts_used = false;
2402 default_rule = 26214; /* revert to default rule thickness */
2403 pseudo_tilde = false;
2404 pseudo_space = false;
2405 show_texinput_flag = false;
2406 truncate_long_lines = false;
2407 allow_quoted_names = false;
2408 show_cs_names = false;
2409 font_dimen_zero = false; /* 98/Oct/5 */
2410 ignore_frozen = false; /* 98/Oct/5 */
2411 suppress_f_ligs = false; /* 99/Jan/5 */
2412 full_file_name_flag = false; // 00 Jun 18
2413 save_strings_flag = false; // 00 Aug 15
2414 knuth_flag = true; /* so other code can know about this */
2415 } /* end of knuthify */
2417 /* following have already been used up */
2419 /* abcdefghijklmnopqrstuvwxyz */
2421 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2425 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2427 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2429 /* following made global so analyze_flag can be made separate procedure */
2431 // char *xchrfile=""; /* save space use xstrdup */
2432 char *xchrfile = NULL; /* save space use xstrdup */
2433 // char *replfile="";/* save space use xstrdup */
2434 char *replfile = NULL;/* save space use xstrdup */
2436 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2438 /* analyze command line flag or argument */
2439 /* c is the flag letter itself, while optarg is start of arg if any */
2441 /* when making changes, revise allowedargs */
2444 int analyze_flag (int c, char *optarg)
2448 want_version = true;
2449 verbose_flag = true;
2455 interaction = batch_mode; /* quiet mode */
2458 interaction = nonstop_mode; /* run mode */
2461 interaction = scroll_mode; /* scroll mode */
2464 interaction = error_stop_mode; /* tex mode */
2467 backwardflag = true; /* 94/Jun/15 */
2468 knuthify(); /* revert to `standard' Knuth TeX */
2471 c_style_flag = true; /* C style error msg 94/Mar/21 */
2474 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2477 current_tfm = false; /* not look current dir for TFM */
2480 current_flag = false; /* not look current dir for files */
2483 show_missing = false; /* do not show missing 94/June/10 */
2486 deslash = false; /* flipped 93/Nov/18 */
2487 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2490 allow_patterns = true; /* 93/Nov/26 */
2491 /* reset_exceptions = true; */ /* 93/Dec/23 */
2493 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2495 show_in_hex = true; /* flipped 00/Jun/18 */
2498 show_in_dos = true; /* 96/Jan/26 */
2501 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2504 workingdirectory = true; /* use source dir 98/Sep/29 */
2507 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2510 show_fonts_used = false; /* 97/Dec/24 */
2513 shorten_file_name = true; /* 95/Feb/20 */
2516 show_cs_names = true; /* 98/Mar/31 */
2519 ignore_frozen = true; /* 98/Oct/5 */
2522 font_dimen_zero = false; /* 98/Oct/5 */
2525 show_texinput_flag = false; /* 98/Jan/28 */
2527 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2530 usedviwindo = false; /* 94/May/19 */
2533 show_line_break_stats = false; /* 96/Feb/8 */
2536 show_fmt_flag = false; /* 94/Jun/21 */
2539 format_specific = false; /* 95/Jan/7 */
2542 encoding_specific = false; /* 98/Oct/5 */
2545 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2547 /* following are pretty obscure */
2548 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2550 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2552 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2555 full_file_name_flag = false; // 00 Jun 18
2558 save_strings_flag = false; // 00 Aug 15
2560 /* following are unannounced options */ /* some may be recycled ... */
2565 quitflag++; /* 93/Dec/16 */
2567 /* The following are really obscure and should not be advertized */
2569 show_current = false; /* tex8 93/Dec/14 */
2572 show_numeric = false; /* 93/Dec/21 */
2575 civilize_flag = false; /* 93/Dec/16 */
2578 open_trace_flag = true; /* openinou 1994/Jan/8 */
2581 reorder_arg_flag = false; /* local */
2584 test_dir_access = false; /* 94/Feb/10 */
2587 dir_method = false; /* 94/Feb/10 */
2590 file_method = false; /* 94/Feb/13 */
2592 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2593 /* case 'X': nohandler++; break; */
2594 /* case 'f': waitflush = false; break; */
2595 /* case 'F': floating = true; break; */
2596 /* *********** following command line options take arguments ************** */
2599 mem_initex = mem_top;
2601 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2602 if (mem_initex == 0)
2603 complainarg(c, optarg);
2606 #ifdef VARIABLETRIESIZE
2609 trie_size = default_trie_size;
2611 trie_size = atoi(optarg); /* 93 Dec/1 */
2613 complainarg(c, optarg);
2616 #ifdef ALLOCATEHYPHEN
2619 new_hyphen_prime = hyphen_prime * 2;
2621 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2622 if (new_hyphen_prime == 0)
2623 complainarg(c, optarg);
2626 #ifdef ALLOCATEDVIBUF
2629 dvi_buf_size = default_dvi_buf_size;
2631 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2632 if (dvi_buf_size == 0)
2633 complainarg(c, optarg);
2640 percent_grow = atoi(optarg); /* 93/Dec/11 */
2641 if (percent_grow == 0)
2642 complainarg(c, optarg);
2648 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2649 if (pseudo_tilde > 255)
2651 else if (pseudo_tilde < 128)
2654 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2655 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2661 tab_step = atoi(optarg); /* 94/July/3 */
2663 complainarg(c, optarg);
2667 xchrfile = xstrdup("xchr.map");
2669 xchrfile = xstrdup(optarg);
2670 if (xchrfile == NULL || *xchrfile == '\0')
2671 complainarg(c, optarg);
2675 replfile = xstrdup("repl.key");
2677 replfile = xstrdup(optarg);
2678 if (replfile == NULL || *replfile == '\0')
2679 complainarg(c, optarg);
2681 /* more obscure stuff - ppssibly recycle */
2684 default_rule = 26214; /* 95/Oct/9 */
2686 default_rule = atoi(optarg); /* 95/Oct/9 */
2687 if (default_rule == 0)
2688 complainarg(c, optarg);
2694 complainarg(c, optarg);
2700 dvi_directory = xstrdup(optarg);
2701 if (strcmp(dvi_directory, "") == 0)
2702 complainarg(c, optarg);
2708 log_directory = xstrdup(optarg);
2709 if (strcmp(log_directory, "") == 0)
2710 complainarg(c, optarg);
2716 aux_directory = xstrdup(optarg);
2717 if (strcmp(aux_directory, "") == 0)
2718 complainarg(c, optarg);
2723 return -1; // failed to recognize
2729 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2730 //char *yytexcmd="yandytex.cmd";
2731 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2733 /* Try and read default command file - YANDYTEX.CMD */
2734 /* in current directory and then in directory of YANDYTEX */
2735 /* (does not make sense in TeX file directory) */
2736 /* since we don't yet know where that is ! */
2737 /* can't conveniently include this in output file either - not open yet */
2739 /* used both for yytex.cmd and @ indirect command line files */
2740 /* can this be reentered ? */
2742 /* supply extension if none */
2743 void yy_extension (char *fname, char *ext)
2746 if ((s = strrchr(fname, '.')) == NULL ||
2747 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2753 /* remove file name - keep only path - inserts '\0' to terminate */
2755 void strip_name (char *pathname)
2758 if ((s = strrchr(pathname, '\\')) != NULL);
2759 else if ((s = strrchr(pathname, '/')) != NULL);
2760 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2765 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2767 char *programpath = ""; /* pathname of program */
2768 /* redundant with texpath ? */
2770 /* The following does not deslashify arguments ? Do we need to ? */
2772 int read_commands (char *filename)
2774 char commandfile[PATH_MAX];
2776 char line[PATH_MAX];
2777 char *linedup; /* need to copy line to preserve args */
2783 /* Try first in current directory (or use full name as specified) */
2784 strcpy(commandfile, filename);
2785 yy_extension(commandfile, "cmd");
2786 if (share_flag == 0)
2787 command = fopen(commandfile, "r");
2789 command = _fsopen(commandfile, "r", share_flag);
2790 if (command == NULL) {
2791 /* If that fails, try in YANDYTeX program directory */
2792 strcpy(commandfile, programpath);
2793 /* don't need fancy footwork, since programpath non-empty */
2794 strcat(commandfile, "\\");
2795 strcat(commandfile, filename);
2796 yy_extension(commandfile, "cmd");
2797 if (share_flag == 0)
2798 command = fopen(commandfile, "r");
2800 command = _fsopen(commandfile, "r", share_flag);
2801 if (command == NULL) {
2802 /* perrormod(commandfile); */ /* debugging only */
2803 /* strcpy(commandfile, ""); */ /* indicate failed */
2804 return 0; /* no command line file YYTEX.CMD */
2808 /* allow for multiple lines --- ignore args that don't start with `-' */
2809 while (fgets(line, PATH_MAX, command) != NULL) {
2810 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2811 /* skip over comment lines and blank lines */
2812 if (*line == '%' || *line == ';' || *line == '\n') continue;
2813 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2814 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2815 linedup = xstrdup (line); /* 93/Nov/15 */
2816 if (linedup == NULL) {
2817 show_line("ERROR: out of memory\n", 1); /* read_commands */
2819 return -1; // failure
2821 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2823 if (*s == '-' || *s == '/') {
2826 /* if (*optarg = '=') optarg++; */
2827 if (*optarg == '=') optarg++;
2828 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2830 /* else break; */ /* ignore non-flag items */
2831 s = strtok(NULL, " \t\n\r"); /* go to next token */
2833 /* If you want to see command lines in file - put -v in the file */
2834 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2836 (void) fclose(command); /* no longer needed */
2837 return 1; // success
2840 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2842 /* try and read commands on command line */
2843 int read_command_line (int ac, char **av)
2846 char *optargnew; /* equal to optarg, unless that starts with `=' */
2847 /* in which case it is optarg+1 to step over the `=' */
2848 /* if optarg = 0, then optargnew = 0 also */
2850 // show_line("read_command_line\n", 0);
2851 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2853 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2854 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2855 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2856 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2857 if (optarg != 0 && *optarg == '=')
2858 optargnew = optarg+1;
2861 analyze_flag (c, optargnew);
2863 if (show_use || quitflag == 3) {
2864 // showversion (stdout);
2866 strcat(log_line, "\n");
2867 show_line(log_line, 0);
2868 stampcopy(log_line);
2869 strcat(log_line, "\n");
2870 show_line(log_line, 0);
2871 if (show_use) show_usage(av[0]);
2872 else if (quitflag == 3) {
2873 strcat(log_line, "\n");
2874 show_line(log_line, 0);
2877 return -1; // failure
2880 if (floating) testfloating(); /* debugging */
2883 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2884 if (read_xchr_file(replfile, 1, av)) {
2885 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2889 /* key_replace used in texmf.c (input_line) */
2890 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2891 if (read_xchr_file(xchrfile, 0, av)) {
2892 if (trace_flag) show_line("NON ASCII ON\n", 0);
2896 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2897 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2902 void uppercase (char *s)
2905 while ((c = *s) != '\0') {
2906 /* if (islower(c)) *s = toupper (*s); */
2913 int init_commands (int ac, char **av)
2915 /* NOTE: some defaults changed 1993/Nov/18 */
2916 /* want_version = show_use = switchflag = return_flag = false;
2917 is_initex = trace_flag = deslash = non_ascii = false; */
2918 is_initex = false; /* check for dumping format file */
2919 allow_patterns = false; /* using \pattern after format file loaded */
2920 reset_exceptions = false;
2922 key_replace = false;
2923 want_version = false;
2924 open_trace_flag = false;
2926 verbose_flag = false;
2928 restrict_to_ascii = false;
2929 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2930 show_in_dos = false; /* default is not to translate to DOS 850 */
2931 return_flag = true; // hard wired now
2932 trimeof = true; // hard wired now
2934 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2935 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2936 default_rule = 26214; /* default rule variable 95/Oct/9 */
2937 show_current = true;
2938 civilize_flag = true;
2939 show_numeric = true;
2940 show_missing = true;
2941 current_flag = true;
2942 current_tfm = true; /* search for TFMs in current dir as well */
2943 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2944 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2945 file_method = true; /* use file_p (_findfirst) not readable (access) */
2946 /* waitflush = true; */ /* flushed 97/Dec/24 */
2947 c_style_flag = false; /* use c-style error output */
2948 show_fmt_flag = true; /* show format file in log */
2949 show_tfm_flag = false; /* don't show metric file in log */
2950 shorten_file_name = false; /* don't shorten file names to 8+3 */
2951 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2952 truncate_long_lines = true; /* truncate long lines */
2953 tab_step = 0; /* do not replace tabs with spaces */
2954 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2955 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2956 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2957 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2958 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2959 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2960 knuth_flag = false; /* allow extensions to TeX */
2961 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2962 full_file_name_flag = true; /* new default 2000 June 18 */
2963 save_strings_flag = true; // 2000 Aug 15
2964 errout = stdout; /* as opposed to stderr say --- used ??? */
2965 abort_flag = 0; // not yet hooked up ???
2966 err_level = 0; // not yet hooked up ???
2967 new_hyphen_prime = 0;
2968 #ifdef VARIABLETRIESIZE
2969 /* trie_size = default_trie_size; */
2975 #ifdef ALLOCATEDVIBUF
2978 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2979 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2980 share_flag = 0; /* revert to fopen for now */
2982 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2983 programpath = xstrdup(av[0]); /* extract path executable */
2984 strip_name(programpath); /* strip off yandytex.exe */
2986 //format_name = "yandytex";
2987 format_name = "plain"; /* format name if specified on command line */
2991 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
2992 return -1; // in case of error
2994 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
2995 return -1; // in case of error
2997 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
2999 /* Print version *after* banner ? */ /* does this get in log file ? */
3001 // showversion (stdout);
3002 // showversion (log_line);
3004 strcat(log_line, "\n");
3005 show_line(log_line, 0);
3006 stampcopy(log_line);
3007 strcat(log_line, "\n");
3008 show_line(log_line, 0);
3010 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
3012 /* if we aren't including current directory in any directory lists */
3013 /* then makes no sense to avoid them separately for TFM files ... */
3014 /* (that is, the ./ is already omitted from the dir list in that case */
3015 if (!current_flag && !current_tfm)
3016 current_tfm = true; /* 94/Jan/24 */
3017 return 0; // success
3020 /* E sets environment variable ? */
3022 void initial_memory (void)
3024 /* set initial memory allocations */
3025 if (mem_extra_high < 0) mem_extra_high = 0;
3026 if (mem_extra_low < 0) mem_extra_low = 0;
3027 if (mem_initex < 0) mem_initex = 0;
3029 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3030 if (mem_extra_high != 0 || mem_extra_low != 0) {
3031 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3032 mem_extra_high = 0; mem_extra_low = 0;
3036 if (mem_initex != 0) {
3037 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3040 if (trie_size != 0) {
3041 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3042 /* trie_size = 0; */
3045 if (mem_initex == 0) mem_initex = default_mem_top;
3046 if (trie_size == 0) trie_size = default_trie_size;
3047 /* Just in case user mistakenly specified words instead of kilo words */
3048 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3049 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3050 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3051 #ifdef ALLOCATEHIGH /* not used anymore */
3052 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3053 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3054 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3057 #ifdef ALLOCATELOW /* not used anymore */
3058 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3059 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3060 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3063 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3064 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3065 /* mem_initex = 2048 * 1024; */
3067 #ifdef ALLOCATEDVIBUF
3068 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3069 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3070 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3071 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3072 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3074 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3075 if (new_hyphen_prime > 0) {
3077 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3079 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3080 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3082 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3083 show_line(log_line, 0);
3087 if (percent_grow > 100) percent_grow = percent_grow - 100;
3088 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3089 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3092 /**********************************************************************/
3094 void perrormod (char *s)
3096 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3097 show_line(log_line, 1);
3103 fflush(stdout); /* ??? */
3104 fflush(stderr); /* ??? */
3105 (void) _getch(); /* ??? */
3109 void checkpause (int flag)
3112 int debug_pause = 0;
3113 /* don't stop if in Q (quiet) or R (run) mode */
3114 /* stop only in S (scroll) and T (TeX) mode */
3115 if (interaction >= 0 && interaction < 2) flag = 0; /* 98/Jun/30 */
3116 s = grabenv("DEBUGPAUSE");
3117 if (s != NULL) sscanf(s, "%d", &debug_pause);
3118 if (flag < 0) return;
3120 if (debug_pause || flag > 0) {
3123 show_line("Press any key to continue . . .\n", 0);
3130 void check_enter (int argc, char *argv[])
3133 char current[FILENAME_MAX];
3134 if (grabenv("DEBUGPAUSE") != NULL) {
3135 (void) _getcwd(current, sizeof(current));
3136 sprintf(log_line, "Current directory: `%s'\n", current);
3137 show_line(log_line, 0);
3138 for (m = 0; m < argc; m++) {
3139 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3140 show_line(log_line, 0);
3147 void checkexit (int n) { /* 95/Oct/28 */
3153 /*************************************************************************/
3155 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3156 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3157 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3158 /* this is then undone in tex3.c both for fopen input and output */
3159 /* not ideal, since pseudo name appears in log and in error messages ... */
3161 void hidetwiddle (char *name)
3166 sprintf(log_line, "Hidetwiddle %s", name);
3167 show_line(log_line, 0);
3170 /* while (*s != '\0' && *s != ' ') { */
3171 while (*s != '\0') {
3172 if (*s == '~' && pseudo_tilde != 0)
3173 *s = (char) pseudo_tilde; /* typically 254 */
3174 else if (*s == ' ' && pseudo_space != 0)
3175 *s = (char) pseudo_space; /* typically 255 */
3180 sprintf(log_line, "=> %s\n", name);
3181 show_line(log_line, 0);
3186 void deslash_all (int ac, char **av)
3188 char buffer[PATH_MAX];
3191 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3192 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3194 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3196 check_enter(ac, av); /* 95/Oct/28 */
3198 /* environment variables for output directories (as in PC TeX) */
3200 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3201 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3202 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3204 strcpy(buffer, av[0]); /* get path to executable */
3205 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3206 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3207 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3208 s = buffer + strlen(buffer) - 1;
3209 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3210 texpath = xstrdup(buffer);
3212 /* Hmm, we may be operating on DOS environment variables here !!! */
3214 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3215 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3216 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3219 unixify (texpath); /* 94/Jan/25 */
3220 /* if output directories given, deslashify them also 1993/Dec/12 */
3221 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3222 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3223 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3226 /* deslash TeX source file (and format, if format specified) */
3227 /* and check args to see whether format was specified */
3229 /* NOTE: assuming that command line arguments are in writable memory ! */
3230 /* if (trace_flag || debug_flag)
3231 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3232 /* if (optind < ac) { */ /* bkph */
3233 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3235 if (trace_flag || debug_flag) {
3236 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3237 optind, av[optind], ac);
3238 show_line(log_line, 0);
3240 unixify(av[optind]);
3242 if (pseudo_tilde != 0 || pseudo_space != 0)
3243 hidetwiddle (av[optind]); /* 95/Sep/25 */
3244 /* For Windows NT, lets allow + instead of & for format specification */
3245 if (*av[optind] == '&' || *av[optind] == '+') {
3246 format_spec = 1; /* format file specified */
3247 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3248 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3249 if (optind + 1 < ac) {
3251 if (trace_flag || debug_flag) {
3252 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3253 optind+1, av[optind+1], ac);
3254 show_line(log_line, 0);
3256 unixify(av[optind+1]);
3258 if (pseudo_tilde != 0 || pseudo_space != 0)
3259 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3265 /* The above seems to assume that arguments that don't start with '-' */
3266 /* are file names or format names - what if type in control sequences? */
3268 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3270 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3271 /* interaction == 1 => nonstop mode (omit all stops) */
3272 /* interaction == 2 => scroll mode (omit error stops) */
3273 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3275 /* main entry point follows */
3277 /* this gets called pretty much right away in `main' in texmf.c */
3279 /* note: those optarg == 0 test don't really work ... */
3280 /* note: optarg starts at = in case of x=... */
3282 int init (int ac, char **av)
3284 char initbuffer[PATH_MAX];
3287 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3294 show_line("TEXDEBUG\n", 0);
3295 trace_flag = 1; /* 94/April/14 */
3298 if (sizeof(memory_word) != 8) { /* compile time test */
3299 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3300 show_line(log_line, 1);
3303 start_time = clock(); /* get time */
3304 main_time = start_time; /* fill in, in case file never opened */
3306 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3308 /* reset all allocatable memory pointers to NULL - in case we drop out */
3313 #ifdef ALLOCATEZEQTB
3319 #ifdef ALLOCATESAVESTACK
3322 #ifdef ALLOCATEDVIBUF
3325 #ifdef ALLOCATEBUFFER
3326 buffer = NULL; /* new 1999/Jan/7 need to do early */
3327 current_buf_size = 0;
3328 buffer = realloc_buffer (initial_buf_size);
3329 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3331 hyph_list = NULL; hyph_word = NULL;
3332 trie_taken = NULL; trie_hash = NULL;
3341 log_opened = false; /* so can tell whether opened */
3342 interaction = -1; /* default state => 3 */
3343 missing_characters = 0; /* none yet! */
3344 workingdirectory = false; /* set from dviwindo.ini & command line */
3345 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3346 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3347 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3348 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3349 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3351 if (reorder_arg_flag) reorderargs(ac, av);
3353 if (init_commands(ac, av))
3354 return -1; // failure
3356 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3358 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3359 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3360 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3361 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3362 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3364 first_pass_count = 0;
3365 second_pass_count = 0;
3366 final_pass_count = 0;
3367 paragraph_failed = 0;
3374 closed_already=0; // so can only do once
3376 if (trace_flag) show_line("Entering init (local)\n", 0);
3378 /* Print version *after* banner ? */ /* does this get in log file ? */
3380 probe_memory(); /* show top address */
3381 ini_max_address = max_address; /* initial max address */
3382 if (trace_flag) show_maximums(stdout);
3384 if (heap_flag) (void) heap_dump(stdout, 1);
3389 deslash_all(ac, av); /* deslash and note if format specified */
3391 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3395 if (format_spec && mem_spec_flag) {
3396 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3399 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3400 return -1; // if failed to allocate
3402 /* following is more or less useless since most all things not yet alloc */
3403 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3405 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3409 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3412 if (trace_flag) show_line("Leaving init (local)\n", 0);
3413 return 0; // success
3416 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3418 /* void show_inter_val (clock_t start, clock_t end) { */
3419 void show_inter_val (clock_t interval)
3421 /* clock_t interval; */
3422 /* int seconds, tenths; */
3423 /* int seconds, tenths, hundredth; */
3424 int seconds, tenths, hundredth, thousands;
3425 /* interval = end - start; */
3426 /* sanity check whether positive ? */
3427 if (interval >= CLK_TCK * 10) {
3428 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3429 seconds = tenths / 10;
3430 tenths = tenths % 10;
3431 sprintf(log_line, "%d.%d", seconds, tenths);
3432 show_line(log_line, 0);
3434 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3435 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3436 seconds = hundredth / 100;
3437 hundredth = hundredth % 100;
3438 sprintf(log_line, "%d.%02d", seconds, hundredth);
3439 show_line(log_line, 0);
3441 else if (interval > 0) { /* 94/Oct/4 */
3442 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3443 seconds = thousands / 1000;
3444 thousands = thousands % 1000;
3445 sprintf(log_line, "%d.%03d", seconds, thousands);
3446 show_line(log_line, 0);
3448 else show_line("0", 0); /* 95/Mar/1 */
3451 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3452 /* shows various times, warning about missing chars */
3454 int endit (int flag)
3457 finish_time = clock();
3458 if (missing_characters != 0) flag = 1;
3459 if (missing_characters) {
3461 "! There %s %d missing character%s --- see log file\n",
3462 (missing_characters == 1) ? "was" : "were", missing_characters,
3463 (missing_characters == 1) ? "" : "s");
3464 show_line(log_line, 0);
3466 if (free_memory() != 0) flag++;
3468 /* show per page time also ? */
3470 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3471 start_time, main_time, finish_time); */
3472 show_line("Total ", 0);
3473 /* show_inter_val(start_time, finish_time); */
3474 show_inter_val(finish_time - start_time);
3475 show_line(" sec (", 0);
3476 /* show_inter_val(start_time, main_time); */
3477 show_inter_val(main_time - start_time);
3478 show_line(" format load + ", 0);
3479 /* show_inter_val(main_time, finish_time); */
3480 show_inter_val(finish_time - main_time);
3481 show_line(" processing) ", 0);
3482 if (total_pages > 0) {
3483 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3484 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3485 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3486 show_inter_val ((finish_time - main_time) / total_pages);
3487 show_line(" sec per page", 0);
3497 /********************************************************************************/
3499 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3503 #define MAXCOLUMN 78
3505 void print_cs_name (FILE *output, int h)
3510 textof = hash[h].v.RH;
3511 if (textof == 0) return; /* ignore if text() == 0 */
3513 if (textcolumn != 0) {
3514 sprintf(log_line, ", ");
3515 if (output != NULL) fprintf(output, log_line);
3516 else show_line(log_line, 0);
3519 if (textcolumn + n + 2 >= MAXCOLUMN) {
3520 sprintf(log_line, "\n");
3521 if (output == stderr) show_line(log_line, 1);
3522 else if (output == stdout) show_line(log_line, 0);
3523 else fputs(log_line, output);
3527 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3530 if (output == stderr) show_line(log_line, 1);
3531 else if (output == stdout) show_line(log_line, 0);
3532 else fprintf(output, log_line);
3536 int compare_strn (int, int, int, int); /* in tex9.c */
3538 /* compare two csnames in qsort */
3540 int compare_cs (const void *cp1, const void *cp2)
3542 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3545 textof1 = hash[c1].v.RH;
3546 textof2 = hash[c2].v.RH;
3547 l1 = length(textof1);
3548 l2 = length(textof2);
3549 k1 = str_start[textof1];
3550 k2 = str_start[textof2];
3551 /* showstring (k1, l1); */
3552 /* showstring (k2, l2); */
3553 return compare_strn (k1, l1, k2, l2);
3558 /* Allocate table of indeces to allow sorting on csname */
3559 /* Allocate flags to remember which ones already listed at start */
3561 void print_cs_names (FILE *output, int pass)
3563 int h, k, ccount, repeatflag;
3565 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3567 if (pass == 0 && csused == NULL) {
3568 csused = (char *) malloc (nfcs);
3569 if (csused == NULL) return;
3571 memset(csused, 0, nfcs);
3573 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3578 for (h = hash_base + 1; h < nfcs; h++) {
3579 if (pass == 1 && csused[h]) continue;
3580 if (hash[h].v.RH != 0) {
3581 if (pass == 0) csused[h] = 1;
3586 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3587 ccount, (pass == 1) ? "new" : "");
3588 if (output == stderr) show_line(log_line, 1);
3589 else if (output == stdout) show_line(log_line, 0);
3590 else fprintf(output, log_line);
3592 if (ccount > 0) { /* don't bother to get into trouble */
3594 cnumtable = (int *) malloc (ccount * sizeof(int));
3595 if (cnumtable == NULL) return;
3598 /* for (h = 515; h < (hash_size + 780); h++) { */
3599 for (h = hash_base+1; h < nfcs; h++) {
3600 if (pass == 1 && csused[ h]) continue;
3601 if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3604 qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3607 for (k = 0; k < ccount; k++) {
3609 if (pass == 1 && csused[ h]) continue;
3610 print_cs_name(output, h);
3612 sprintf(log_line, "\n");
3613 if (output == stderr) show_line(log_line, 1);
3614 else if (output == stdout) show_line(log_line, 0);
3615 else fprintf(output, log_line);
3616 free((void *)cnumtable);
3619 if (pass == 1 && csused != NULL) {
3625 /***************** font info listing moved from TEX9.C ******************/
3627 void showstring (int k, int l)
3630 while (l-- > 0) *s++ = str_pool[k++];
3633 show_line(log_line, 0);
3636 /* compare two strings in str_pool (not null terminated) */
3637 /* k1 and k2 are positions in string pool */
3638 /* l1 and l2 are lengths of strings */
3640 int compare_strn (int k1, int l1, int k2, int l2)
3643 /* while (l1-- > 0 && l2-- > 0) { */
3644 while (l1 > 0 && l2 > 0) {
3647 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3648 if (c1 > c2) return 1;
3649 else if (c2 > c1) return -1;
3653 if (l1 > 0) return 1; /* first string longer */
3654 else if (l2 > 0) return -1; /* second string longer */
3655 return 0; /* strings match */
3658 /* compare two font names and their at sizes in qsort */
3660 int compare_fnt (const void *fp1, const void *fp2)
3662 int f1, f2, l1, l2, k1, k2, s;
3665 l1 = length(font_name[f1]);
3666 l2 = length(font_name[f2]);
3667 k1 = str_start[font_name[f1]];
3668 k2 = str_start[font_name[f2]];
3669 /* showstring (k1, l1); */
3670 /* showstring (k2, l2); */
3671 s = compare_strn (k1, l1, k2, l2);
3672 /* sprintf(log_line, "%d\n", s); */
3673 if (s != 0) return s;
3674 if (font_size[f1]> font_size[f2]) return 1;
3675 else if (font_size[f1]< font_size[f2]) return -1;
3676 return 0; /* should not ever get here */
3679 /* compare two font names */
3681 int compare_fnt_name (int f1, int f2)
3683 int l1, l2, k1, k2, s;
3684 l1 = length(font_name[f1]);
3685 l2 = length(font_name[f2]);
3686 k1 = str_start[font_name[f1]];
3687 k2 = str_start[font_name[f2]];
3688 /* showstring (k1, l1); */
3689 /* showstring (k2, l2); */
3690 s = compare_strn (k1, l1, k2, l2);
3691 /* sprintf(log_line, "%d\n", s); */
3695 /* decode checksum information */
3697 unsigned long checkdefault = 0x59265920; /* default signature */
3699 int decode_fourty (unsigned long checksum, char *codingvector)
3703 /* char codingvector[6+1]; */
3705 /* if (checksum == checkdefault) { */
3706 if (checksum == 0) {
3707 /* strcpy(codingvector, "unknown"); */
3708 strcpy(codingvector, "unknwn");
3711 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3712 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3713 strcpy (codingvector, "fixed "); /* if not specified ... */
3714 return 1; /* no info available */
3717 for (k = 0; k < 6; k++) {
3718 c = (int) (checksum % 40);
3719 checksum = checksum / 40;
3720 if (c <= 'z' - 'a')c = c + 'a';
3721 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3722 else if (c == 36) c = '-';
3723 else if (c == 37) c = '&';
3724 else if (c == 38) c = '_';
3725 else c = '.'; /* unknown */
3726 codingvector[5-k] = (char) c;
3728 codingvector[6] = '\0';
3730 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3731 return 0; /* encoding info returned in codingvector */
3734 double sclpnt (long x)
3737 pt = (double) x / 65536.0;
3738 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3742 // Shows list of fonts in log file
3744 void dvi_font_show(internal_font_number f, int suppressname)
3746 int a, l, k, n, for_end;
3747 unsigned long checksum;
3748 char checksumvector[8];
3751 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3752 /* fprintf (log_file, "%d ", suppressname); */
3753 /* suppressname = 0; */
3754 putc(' ', log_file);
3755 if (suppressname == 0) {
3756 a = length(font_area[f]);
3757 l = length(font_name[f]);
3758 k = str_start[font_area[f]];
3759 for_end = str_start[font_area[f]+ 1]- 1;
3760 if (k <= for_end) do {
3761 putc(str_pool[k], log_file);
3762 } while(k++ < for_end, stdout);
3763 k = str_start[font_name[f]];
3764 for_end = str_start[font_name[f]+ 1]- 1;
3765 if (k <= for_end) do {
3766 putc(str_pool[k], log_file);
3767 } while(k++ < for_end);
3770 for (k = a+l; k < 16; k++) putc(' ', log_file);
3771 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3772 fputs(buffer, log_file);
3773 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3774 if (suppressname == 0) {
3776 // n = strlen(log_file);
3777 for (k = n; k < 16; k++) putc(' ', log_file);
3778 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3779 font_check[f].b2) << 8 | font_check[f].b3;
3780 decode_fourty(checksum, checksumvector);
3781 fprintf(log_file, "encoding: %s..", checksumvector);
3783 putc('\n', log_file);
3786 /* Allocate table of indeces to allow sorting on font name */
3788 void show_font_info (void)
3790 int k, m, fcount, repeatflag;
3794 for (k = 1; k <= font_ptr; k++)
3795 if (font_used[k])fcount++;
3797 if (fcount == 0) return; /* don't bother to get into trouble */
3799 fnumtable = (short *) malloc (fcount * sizeof(short));
3801 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3803 fprintf(log_file, "\nUsed %d font%s:\n",
3804 fcount, (fcount == 1) ? "" : "s");
3807 for (k = 1; k <= font_ptr; k++)
3808 if (font_used[k])fnumtable[fcount++] = (short) k;
3810 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3813 for (m = 0; m < fcount; m++) {
3815 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3817 else repeatflag = 0;
3819 dvi_font_show(fnumtable[ m], repeatflag);
3822 free((void *)fnumtable);
3825 ////////////////////////////////////////////////////////////////////////////
3827 // Here follows the new stuff for the DLL version
3833 #define SHOWLINEBUFLEN 256
3835 char showlinebuf[SHOWLINEBUFLEN];
3837 // char log_line[MAXLINE];
3839 #define WHITESPACE " \t\n\r"
3841 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3843 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3845 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3846 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3847 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3849 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3851 void ClearShowBuffer (void)
3853 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3854 if (hConsoleWnd != NULL)
3855 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3859 // communicate with DVIWindo (for yandytex.dll)
3861 void show_line (char *line, int errflag) { /* 99/June/11 */
3864 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3865 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3866 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3868 // abort_flag++; // kill job in this case ???
3872 if (showlineinx > 0) ClearShowBuffer();
3874 if (hConsoleWnd != NULL)
3875 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3879 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3880 if (ret == IDCANCEL) {
3882 uexit(1); // dangerous reentry possibility ?
3887 // Provide means for buffering up individual characters
3889 void show_char (int chr) {
3890 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3891 showlinebuf[showlineinx++] = (char) chr;
3892 if (chr == '\n') ClearShowBuffer();
3895 void winshow(char *line) {
3896 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3899 void winerror (char *line) {
3901 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3902 if (ret == IDCANCEL) abort_flag++;
3905 // argument info constructed from command line
3911 // need to be careful here because of quoted args with spaces in them
3912 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3914 int makecommandargs (char *line)
3918 unsigned char *s, *t; // fix 2000 June 18
3920 if (line == NULL) return -1; /* sanity check */
3922 // winerror(line); // debugging only
3924 // s = strtok(line, WHITESPACE);
3925 // while (s != NULL) { /* count arguments */
3927 // s = strtok(NULL, WHITESPACE);
3932 while (*s != '\0') {
3933 while (*s <= 32 && *s > 0) s++;
3934 if (*s == '\0') break;
3936 while (*t > 32 && *t != '\"') t++;
3939 while (*t > 0 && *t != '\"') t++;
3940 if (*t == '\0') break;
3943 // xargv[xargc] = s;
3945 if (*t == '\0') break;
3950 if (xargc == 0) return -1; /* nothing to do */
3952 xargv = (char **) malloc(xargc * sizeof(char *));
3953 if (xargv == NULL) {
3954 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3961 while (*s != '\0') {
3962 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3963 if (*s == '\0') break;
3965 while (*t > ' ' && *t != '\"') t++;
3968 while (*t > 0 && *t != '\"') t++;
3969 if (*t == '\0') break;
3972 // winerror(s); // debugging only
3975 if (*t == '\0') break;
3981 // for (k = 0; k < xargc; k++) { /* create pointers to args */
3982 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
3984 // s += strlen(s) +1;
3990 for (k = 0; k < xargc; k++) {
3991 sprintf(s, "%d\t%s\n", k, xargv[k]);
3999 // refers to TeXAsk in dviwindo.c
4001 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4002 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
4004 // called from tex0.c only --- by initterm and term_input
4006 //int ConsoleInput (char *question, char *buffer)
4007 int ConsoleInput (char *question, char *help, char *buffer)
4011 if (AskUserCall == NULL) return 0;
4012 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4013 // show_line(log_line, 1);
4016 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
4017 // strcpy(buffer, "x");
4018 // strcat(buffer, " "); // ???
4019 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4020 // show_line(log_line, 1);
4021 // input_line_finish(); // ???
4022 // s = buffer + strlen(buffer);
4023 // *s++ = ' '; // space terminate
4024 // *s++ = '\0'; // and null terminate
4025 // returning != 0 means EOF or ^Z
4029 // This is the new entry point of DLL called from DVIWindo
4030 // ARGS: console window to send messages to, command line, callback fun
4031 // no console window output if hConsole is NULL
4032 // returns -1 if it fails --- returns 0 if it succeeds
4034 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4035 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4039 abort_flag = 0; // redundant
4040 hConsoleWnd = NULL; // redundant
4042 AskUserCall = AskUser; // remember callback
4044 hConsoleWnd = hConsole; // remember console window handle
4046 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4047 // if (grabenv("DEBUGPAUSE") != NULL) {
4048 // show_line(line, 0); // debugging - show command line
4049 // show_line("\n", 0);
4052 xargc = makecommandargs(line); // sets up global *xargv[]
4054 if (xargc < 0) return -1; // sanity check
4056 if (hConsoleWnd != NULL)
4057 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4058 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4061 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
4063 if (err_level > 0 || abort_flag > 0) {
4064 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4065 // err_level, abort_flag);
4066 // winerror(log_line);
4069 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
4070 // if (psbufpos > 0) PSputs("", output); // output already closed
4072 if (hConsoleWnd != NULL) {
4073 if (err_level > 0 || abort_flag > 0) flag = 1;
4074 else flag = 0; // pass along error indication
4075 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
4077 // PScallback = NULL;
4080 if (xargv != NULL) free(xargv);
4081 if (abort_flag) return -1;
4085 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4088 switch (fdwReason) {
4089 case DLL_PROCESS_ATTACH:
4090 // The DLL is being mapped into the process's address space
4091 // place to allocate memory ???
4092 // return FALSE if this fails
4093 hInstanceDLL = hInstDll; /* remember it */
4096 case DLL_THREAD_ATTACH:
4097 // A thread is being created
4100 case DLL_THREAD_DETACH:
4101 // A thread is exiting cleanly
4104 case DLL_PROCESS_DETACH:
4105 // The DLL is being unmapped from the process's address space
4106 // place to free any memory allocated
4107 // but make sure it in fact *was* allocated
4108 hInstanceDLL = NULL; /* forget it */
4111 return(TRUE); // used only for DLL_PROCESS_ATTACH
4113 #endif // end of new stuff for DLL version
4115 //////////////////////////////////////////////////////////////////////////////
4119 /* NOTE: current_tfm = false (-c)
4120 not checking for TFM in current directory saves 0.1 sec
4121 (0.2 if file_method = false (-G) */
4123 /* NOTE: test_dir_access = false (-b):
4124 not checking whether readable file is a directory saves maybe 0.5 sec
4125 BUT only if file_method = false (-G) - otherwise its irrelevant */
4127 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4128 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4129 BUT not if current_tfm = false (-c) */
4131 /* NOTE: file_method = false (-G) --- method for checking file accessible
4132 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4134 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4136 /* constants for _heapchk/_heapset/_heapwalk routines */
4137 /* #define _HEAPEMPTY (-1) */
4138 /* #define _HEAPOK (-2) */
4139 /* #define _HEAPBADBEGIN (-3) */
4140 /* #define _HEAPBADNODE (-4) */
4141 /* #define _HEAPEND (-5) */
4142 /* #define _HEAPBADPTR (-6) */
4144 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4146 /* buffercopy no longer used */
4148 /* To Knuthian reset right when command line interpreted */