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)
158 " yandytex [-?ivnwdrzpK] [-m=ini_mem] [-e=hyph_size] [-h=trie_size]\n"
159 " [-x=xchr_file] [-k=key_file] [-o=dvi_dir] [-l=log_dir] [-a=aux_dir]\n"
160 " [+format_file] [tex_file]\n\n"
161 " -? show this usage summary\n"
162 " -i start up as iniTeX (create format file)\n"
163 " -v be verbose (show implementation version number)\n"
164 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
165 " -w do not show `non ASCII' characters in hexadecimal (show as is)\n"
166 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
167 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
168 " -p allow use of \\patterns after loading format (iniTeX only)\n"
169 " -K disable all extensions to basic TeX\n"
170 " -m initial main memory size in kilo words (iniTeX only)\n"
171 " -e hyphenation exception dictionary size (iniTeX only)\n"
172 " -h hyphenation pattern trie size (iniTeX only)\n"
173 " -x use `non ASCII' character mapping (xchr[]) defined in file\n"
174 " -k use `key replacement' defined in file\n"
175 " -o write DVI file in specified directory (default current directory)\n"
176 " -l write LOG file in specified directory (default current directory)\n"
177 " -a write AUX file in specified directory (default current directory)");
179 show_line(log_line, 1);
181 uexit(1); // has this been setup yet ???
185 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
187 /* -c prepend current directory (.) to TFM directory list\n\ */
188 /* -b check that files with read access are not actually directories\n\ */
190 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
191 /* \t\t(applies to file name and format file name, if present)\n\ */
192 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
196 /* Sep 27 1990 => 1990 Sep 27 */
197 /* 012456789 0123456789 */
199 void scivilize (char * date)
203 strcpy (pyear, date + 7);
204 for (k = 5; k >= 0; k--) date[k + 5] = date[k];
205 for (k = 0; k < 4; k++) date[k] = pyear[k];
207 if (date[9] == ' ') date[9] = '0'; /* replace space by '0' */
211 /* Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35 */
213 void lcivilize (char * date)
218 strcpy (pyear, date + 20);
219 for (k = 18; k >= 0; k--) date[k+1] = date[k];
220 /* date[20] = '\n'; */
221 /* date[21] = '\0'; */
223 for (k = 0; k < 4; k++) date[k] = pyear[k];
228 // void stamp_it (FILE *outfile)
229 // now writes result into given buffer
230 void stamp_it (char *s)
234 strcpy(date, compiledate);
236 sprintf(s, "%s %s ", application, yandyversion);
238 sprintf(s, "(compiled time: %s %s)", date, compiletime);
242 void stampcopy (char *s)
246 sprintf(s, "%s %s", copyright, www); /* 99/Oct/25 */
250 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
255 void read_xchr_sub (FILE * xchr_input)
257 char buffer[PATH_MAX];
258 int k, from, to, count = 0;
262 memset (xchr, NOTDEF, MAXCHRS); /* mark unused */
264 for (k = 0; k < MAXCHRS; k++) xchr[k]= -1; /* mark unused */
267 memset (xord, NOTDEF, MAXCHRS); /* mark unused */
269 for (k = 0; k < MAXCHRS; k++) xord[k]= -1; /* mark unused */
272 #ifdef ALLOCATEBUFFER
273 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
275 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
278 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
279 /* if (sscanf (buffer, "%d %d", &from, &to) < 2)
280 sprintf(log_line, "Do not understand: %s", buffer); */
281 from = (int) strtol (buffer, &s, 0);
282 to = (int) strtol (s, NULL, 0);
283 /* what if line is bad ? do we just get from = 0 and to = 0 ? */
284 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS) {
285 if (xchr[from]== (unsigned char) NOTDEF)
286 xchr[from]= (unsigned char) to;
288 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
289 show_line(log_line, 0);
291 if (xord[to]== NOTDEF)
292 xord[to]= (unsigned char) from;
294 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
295 show_line(log_line, 0);
300 /* now fill in the gaps */ /* not clear this is a good idea ... */
301 for (k = 0; k < MAXCHRS; k++) {
302 if (xchr[k]== NOTDEF) { /* if it has not been filled */
303 if (xord[k]== NOTDEF) { /* see whether used already */
304 xchr[k]= (unsigned char) k; /* no, so make identity */
305 xord[k]= (unsigned char) k; /* no, so make identity */
309 xchr[NOTDEF]= NOTDEF; /* fixed point of mapping */
311 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
312 show_line(log_line, 0);
313 for (k = 0; k < MAXCHRS; k++) {
314 if (xchr[k]!= NOTDEF) {
315 sprintf(log_line, "%d => %d\n", k, xchr[k]);
316 show_line(log_line, 0);
322 char *replacement[MAXCHRS]; /* pointers to replacement strings */
324 void read_repl_sub (FILE * repl_input)
327 char buffer[PATH_MAX];
333 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
335 for (k = 0; k < MAXCHRS; k++) replacement[k] = NULL;
338 while (fgets(buffer, PATH_MAX, repl_input) != NULL) {
339 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
340 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
343 if (*charname == '"') { /* deal with quoted string "..." */
346 while (*s != '"' && *s != '\0') s++; /* step up to " */
347 if (*s++ == '\0') continue; /* sanity check */
350 s++; /* is it "" perhaps ? */
351 if (*s != '"') break; /* no, end of string */
353 *t++ = *s++; /* copy over */
355 *t = '\0'; /* and terminate */
357 if (chrs >= 0 && chrs < MAXCHRS)
358 replacement[chrs] = xstrdup(charname);
360 /* presently the following can never get triggered */
361 /* which is good, because it is perhaps not right ... */
362 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
363 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
364 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
365 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
366 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
368 if (chrs >= 0 && chrs < MAXCHRS)
369 replacement[chrs] = xstrdup(charname);
372 sprintf(log_line, "ERROR: don't understand %s", buffer);
373 show_line(log_line, 1);
376 if (trace_flag) { /* debugging output */
377 show_line("Key replacement table\n", 0);
378 for (k = 0; k < MAXCHRS; k++) {
379 if (replacement[k] != NULL) {
380 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
381 show_line(log_line, 0);
387 /* Following used both to read xchr[] file and key replacement file */
388 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
390 int read_xchr_file (char *filename, int flag, char *argv[])
393 char infile[PATH_MAX];
396 if (filename == NULL) return -1;
398 sprintf(log_line, "Reading xchr/repl %s\n", filename);
399 show_line(log_line, 0);
402 /* first try using file as specified */
403 strcpy(infile, filename);
405 sprintf(log_line, "Trying %s\n", infile);
406 show_line(log_line, 0);
408 if (share_flag == 0) pinput = fopen (infile, "r");
409 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
410 if (pinput == NULL) {
411 if (strrchr(infile, '.') == NULL) {
412 if (flag == 0) strcat(infile, ".map");
413 else strcat(infile, ".key");
415 sprintf(log_line, "Trying %s\n", infile);
416 show_line(log_line, 0);
418 if (share_flag == 0) pinput = fopen (infile, "r");
419 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
422 if (pinput == NULL) {
423 /* strcpy (infile, gargv[0]); */ /* try TeX program path */
424 strcpy (infile, argv[0]); /* try TeX program path */
425 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
426 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
427 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
428 strcat (infile, filename);
430 sprintf(log_line, "Trying %s\n", infile);
431 show_line(log_line, 0);
433 if (share_flag == 0) pinput = fopen (infile, "r");
434 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
435 if (pinput == NULL) {
436 if (strchr(infile, '.') == NULL) {
437 if (flag == 0) strcat(infile, ".map");
438 else strcat(infile, ".key");
440 sprintf(log_line, "Trying %s\n", infile);
441 show_line(log_line, 0);
443 if (share_flag == 0) pinput = fopen (infile, "r");
444 else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
448 if (pinput == NULL) { /* 97/July/31 */
449 /* strcpy (infile, gargv[0]); */ /* try TeX program path\keyboard */
450 strcpy (infile, argv[0]); /* try TeX program path */
451 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
452 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
453 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
454 strcat (infile, "keyboard\\");
455 strcat (infile, filename);
457 sprintf(log_line, "Trying %s\n", infile);
458 show_line(log_line, 0);
460 if (share_flag == 0) pinput = fopen (infile, "r");
461 else pinput = _fsopen (infile, "r", share_flag);
462 if (pinput == NULL) {
463 if (strchr(infile, '.') == NULL) {
464 if (flag == 0) strcat(infile, ".map");
465 else strcat(infile, ".key");
467 sprintf(log_line, "Trying %s\n", infile);
468 show_line(log_line, 0);
470 if (share_flag == 0) pinput = fopen (infile, "r");
471 else pinput = _fsopen (infile, "r", share_flag);
475 /* Note: can't look in TeX source file dir, since that is not known yet */
476 if (pinput == NULL) {
477 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
478 flag ? " xchr[]" : "key mapping", filename);
479 show_line(log_line, 1);
480 perrormod (filename);
485 read_xchr_sub (pinput);
487 read_repl_sub (pinput);
489 (void) fclose (pinput);
493 /* need to also set `key_replace' here based on command line */
494 /* need to also allocate `buffercopy' here and free at end */
495 /* need to call `readreplace' in appropriate place */
497 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
499 /* Following may be useful if link without floating point emulation */
502 void testfloating (void) {
503 /* double x = 1.0; */
504 /* double dx = DBL_EPSILON; */
508 /* while (x + dx != 1.0) { */
509 while (1.0 + dx != 1.0) {
514 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
515 show_line(log_line, 0);
519 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
521 char *debugfile; /* NULL or name of file to try and open */
524 char *heapstrings[] = {
525 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
529 /* Attempt to get at problem with eqtb ... temporarily abandoned */
532 void check_eqtb (char *act) {
534 memory_word *eqtb = zeqtb;
535 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
536 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
537 if (eqtb[k].cint != 0) {
540 show_line("EQTB ", 0);
542 sprintf(log_line, "%d ", k);
543 show_line(log_line, 0);
544 if (count++ > 256) break;
547 if (count != 0) show_char('\n');
551 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
555 /* ad hoc default minimum growth in memory realloc is 62% */
556 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
557 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
558 int total_allocated = 0; /* total memory allocated so far */
559 int ini_max_address = 0; /* maximum address when starting */
560 int max_address = 0; /* maximum address seen in allocated memory */
564 // DON'T USE THIS in DLL VERSION
568 unsigned int heapthreshold=0; /* smallest size block interested in ... */
570 unsigned int heap_dump (FILE *output, int verbose)
572 unsigned int total=0;
573 struct _heapinfo hinfo;
578 if (verbose) fprintf(output, "HEAP DUMP:\n");
580 /* if ((n = _heapchk ()) != _HEAPOK) { */
586 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
588 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
591 hinfo._pentry = NULL;
592 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
593 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
594 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
596 end_block = (int) hinfo._pentry + hinfo._size;
597 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
598 if (hinfo._size >= heapthreshold && verbose)
599 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
600 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
601 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
604 switch (heapstatus) {
606 if (verbose) fprintf(output, "OK - empty heap\n");
609 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
612 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
615 fprintf(output, "ERROR - %s\n", "bad start of heap");
618 fprintf(output, "ERROR - %s\n", "bad node in heap");
626 void show_maximums (FILE *output)
629 unsigned heaptotal=0; /* no longer used */
630 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
632 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
633 // if (output != NULL) fputs(log_line, output); // log file
634 // else if (flag == 0) show_line(log_line, 0); // informative
635 // else if (flag == 1) show_line(log_line, 1); // error
636 if (output == stderr) show_line(log_line, 1);
637 else if (output == stdout) show_line(log_line, 0);
638 else fputs(log_line, output);
641 /* our own version of realloc --- avoid supposed MicroSoft version bug */
642 /* also tries _expand first, which can avoid address growth ... */
645 void *ourrealloc (void *old, size_t new_size)
648 size_t old_size, overlap;
650 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
651 if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
653 if (old == NULL) return malloc (new_size); /* no old block - use malloc */
655 old_size = _msize (old);
656 if (old_size >= new_size && old_size < new_size + 4) return old;
657 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
660 show_line("BEFORE REALLOC: \n", 0);
662 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
666 mnew = _expand (old, new_size); /* first try and expand in place */
669 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
670 mnew, new_size, old, old_size);
671 show_line(log_line, 0);
675 /* *********************************************************************** */
676 /* do this if you want to call the real realloc next - */
677 mnew = realloc (old, new_size);
680 show_line("AFTER REALLOC: \n", 0);
682 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
686 if (mnew != NULL) return mnew;
687 /* we are screwed typically if we ever drop through here - no more space */
688 /* *********************************************************************** */
689 mnew = malloc (new_size); /* otherwise find new space */
690 if (mnew == NULL) return mnew; /* if unable to allocate */
691 if (old_size < new_size) overlap = old_size;
692 else overlap = new_size;
693 memcpy (mnew, old, overlap); /* copy old data to new area */
694 free(old); /* free the old area */
699 void memory_error (char *s, int n)
702 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
703 show_maximums(log_file);
705 if (heap_flag) (void) heap_dump(log_file, 1);
708 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
709 show_line(log_line, 1);
710 show_maximums(stderr);
712 if (heap_flag) (void) heap_dump(stderr, 1);
714 /* exit (1); */ /* 94/Jan/22 */
715 /* return to let TeX do its thing (such as complain about runaway) */
716 /* don't set abort_flag here */
719 void trace_memory (char *s, int n)
721 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
722 show_line(log_line, 0);
725 void update_statistics (int address, int size, int oldsize)
727 if (address + size > max_address) max_address = address + size;
728 total_allocated = total_allocated + size - oldsize;
731 void probe_memory (void)
734 s = (char *) malloc (4); /* get current top address */
736 update_statistics ((int) s, 0, 0); /* show where we are */
739 void probe_show (void)
742 show_maximums(stdout);
744 if (heap_flag) (void) heap_dump(stdout, 1);
748 size_t roundup (size_t n)
750 if ((n % 4) == 0) return n;
751 else return ((n / 4) + 1) * 4;
755 /* using allocating hyphenation trie slows things down maybe 1% */
756 /* but saves typically (270k - 55k) = 215k of memory */
757 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
758 /* since hyphenation trie cannot be extended (after iniTeX) */
759 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
761 /* NOTE: we don't ever reallocate these */
762 /* returns -1 if it fails */
764 int allocate_tries (int trie_max)
767 /* if (trie_max > trie_size) {
768 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
769 trie_max, trie_size);
770 show_line(log_line, 1);
772 } */ /* ??? removed 1993/dec/17 */
773 if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
774 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
775 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
776 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
777 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
779 if (trace_flag) trace_memory("hyphen trie", n);
780 trie_trl = (halfword *) malloc (roundup(nl));
781 trie_tro = (halfword *) malloc (roundup(no));
782 trie_trc = (quarterword *) malloc (roundup(nc));
783 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL) {
784 memory_error("hyphen trie", n);
788 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
789 show_line(log_line, 0);
791 update_statistics ((int) trie_trl, nl, 0);
792 update_statistics ((int) trie_tro, no, 0);
793 update_statistics ((int) trie_trc, nc, 0);
794 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
795 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
797 probe_show(); /* 94/Mar/25 */
802 #ifdef ALLOCATEHYPHEN
803 bool prime (int); /* test function later in this file */
805 int current_prime = 0; /* remember in case reallocated later */
807 /* we don't return an address here, since TWO memory regions allocated */
808 /* plus, we don't really reallocate, we FLUSH the old information totally */
809 /* returns -1 if it fails */
811 int realloc_hyphen (int hyphen_prime)
814 if (!prime(hyphen_prime)) {
815 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
816 show_line(log_line, 1);
820 /* need not/cannot preserve old contents when hyphen prime is changed */
821 /* if (hyph_list != NULL) free(hyph_list); */
822 /* if (hyph_word != NULL) free(hyph_word); */
823 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
824 nw = (hyphen_prime + 1) * sizeof(str_number);
825 nl = (hyphen_prime + 1) * sizeof(halfword);
827 if (trace_flag) trace_memory("hyphen exception", n);
828 /* initially hyph_word will be NULL so this acts like malloc */
829 /* hyph_word = (str_number *) malloc (nw); */
830 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
831 /* initially hyph_list will be NULL so this acts like malloc */
832 /* hyph_list = (halfword *) malloc (nl); */
833 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
834 if (hyph_word == NULL || hyph_list == NULL) {
835 memory_error("hyphen exception", n);
839 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
840 show_line(log_line, 0);
842 /* cannot preserve old contents when hyphen prime is changed */
844 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
846 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
849 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
851 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
853 hyph_count = 0; /* or use reset_hyphen() in itex.c */
854 if (current_prime != 0) {
855 update_statistics ((int) hyph_word, nw,
856 (current_prime + 1) * sizeof(str_number));
857 update_statistics ((int) hyph_list, nl,
858 (current_prime + 1) * sizeof(halfword));
861 update_statistics ((int) hyph_word, nw, 0);
862 update_statistics ((int) hyph_list, nl, 0);
864 current_prime = hyphen_prime;
865 if (trace_flag) probe_show(); /* 94/Mar/25 */
870 int current_mem_size=0; /* current total words in main mem allocated -1 */
872 /* this gets called from itex.c when it figures out what mem_top is */
873 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
874 /* initial allocation only, may get expanded later */
875 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
876 /* returns NULL if it fails */
879 /* initial main memory alloc - mem_top */
880 memory_word *allocate_main_memory (int size)
884 /* Using -i *and* pre-loading format */ /* in this case get called twice */
885 /* Get rid of initial blank memory again or use realloc ... */
886 /* Could we avoid this by detecting presence of & before allocating ? */
887 /* Also, if its already large enough, maybe we can avoid this ? */
888 /* don't bother if current_mem_size == mem_max - mem_start ? */
889 if (mainmemory != NULL) {
890 /* free(mainmemory); */
891 /* mainmemory = NULL; */
892 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
893 /* if (mem_spec_flag)
894 show_line("Cannot change initial main memory size when format is read\n", 1);*/
897 mem_top = mem_bot + size;
898 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
899 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
902 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
903 if (mem_extra_low != 0 && !is_initex)
904 mem_start = mem_bot - mem_extra_low; /* increase main memory */
906 mem_start = 0; /* bottom of memory allocated by system */
907 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
908 mem_min = 0; /* bottom of area made available to TeX */
909 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
910 if (trace_flag) trace_memory("main memory", n);
911 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
912 /* normally mainmemory == NULL here so acts like malloc ... */
913 mainmemory = (memory_word *) REALLOC (mainmemory, n);
914 if (mainmemory == NULL) {
915 memory_error("initial main memory", n);
916 // exit (1); /* serious error */
920 sprintf(log_line, "Address main memory == %d\n", mainmemory);
921 show_line(log_line, 0);
924 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
926 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
927 show_line(log_line, 0);
929 update_statistics ((int) mainmemory, n,
930 (current_mem_size + 1) * sizeof (memory_word));
931 /* current_mem_size = (mem_max - mem_start + 1); */
932 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
933 if (trace_flag) probe_show(); /* 94/Mar/25 */
934 return zzzaa; /* same as zmem, mem 94/Jan/24 */
936 #endif /* end of ALLOCATEMAIN */
939 /* int firstallocation = 1; */
941 /* increase main memory allocation at low end and high end */
942 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
943 /* returns NULL if it fails */
945 memory_word *realloc_main (int losize, int hisize)
948 int newsize = 0; /* to quieten compiler */
949 int n = 0; /* to quieten compiler */
950 memory_word * newmemory = NULL; /* to quieten compiler */
952 /* if (losize == 0 && hisize > 0) runawayflag = 1;
953 else runawayflag = 0; */ /* 94/Jan/22 */
956 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
957 show_line(log_line, 0);
960 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
962 show_line("Please use `-m=...' on command line\n", 0);
963 // abort_flag++; // ???
967 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
968 show_line(log_line, 0);
970 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
971 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
972 // abort_flag++; // ???
975 /* first allocation should expand *both* lo and hi */
976 if (hisize == 0 && mem_end == mem_max) hisize = losize;
977 if (losize == 0 && mem_start == mem_min) losize = hisize;
978 /* try and prevent excessive frequent reallocations */
979 /* while avoiding over allocation by too much */
980 minsize = current_mem_size / 100 * percent_grow;
981 if (losize + hisize < minsize) {
982 if (losize > 0 && hisize > 0) {
983 losize = minsize / 2;
984 hisize = minsize / 2;
986 else if (losize > 0) losize = minsize;
987 else if (hisize > 0) hisize = minsize;
989 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
990 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
992 for (k = 0; k < MAXSPLITS; k++) {
993 newsize = current_mem_size + losize + hisize;
994 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
995 while (newsize >= max_mem_size) {
996 losize = losize / 2; hisize = hisize / 2;
997 newsize = current_mem_size + losize + hisize;
1000 n = (newsize + 1) * sizeof (memory_word);
1001 if (trace_flag) trace_memory("main memory", n);
1002 newmemory = (memory_word *) REALLOC (mainmemory, n);
1003 if (newmemory != NULL) break; /* did we get it ? */
1004 if (current_mem_size == 0) break; /* in case we ever use for initial */
1005 losize = losize / 2; hisize = hisize / 2;
1008 if (newmemory == NULL) {
1009 memory_error("main memory", n);
1010 return zzzaa; /* try and continue with TeX !!! */
1013 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1014 show_line(log_line, 0);
1017 /* shift everything upward to make space for new low area */
1019 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1020 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1021 show_line(log_line, 0);
1023 memmove (newmemory + losize, newmemory,
1024 /* current_mem_size * sizeof(memory_word)); */
1025 (current_mem_size + 1) * sizeof(memory_word));
1026 /* could reduce words moved by (mem_max - mem_end) */
1028 mainmemory = newmemory; /* remember for free later */
1029 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1030 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1031 update_statistics ((int) mainmemory, n,
1032 (current_mem_size + 1) * sizeof (memory_word));
1033 current_mem_size = newsize;
1034 if (current_mem_size != mem_max - mem_start) {
1035 show_line("ERROR: Impossible Memory Error\n", 1);
1037 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1038 else zzzaa = mainmemory;
1039 if (trace_flag) probe_show(); /* 94/Mar/25 */
1045 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1047 int current_font_mem_size=0;
1049 /* fmemoryword can be either halfword or memory_word */
1050 fmemoryword *realloc_font_info (int size)
1051 { /* number of memorywords */
1052 fmemoryword *newfontinfo=NULL;
1054 int newsize=0; /* to quieten compiler */
1055 int n=0; /* to quieten compiler */
1058 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1059 show_line(log_line, 0);
1061 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1062 /* during initial allocation current_font_mem_size == 0 */
1063 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1064 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1065 return font_info; /* pass it back to TeX 99/Fabe/4 */
1067 /* try and prevent excessive frequent reallocations */
1068 /* while avoiding over allocation by too much */
1069 /* minsize = current_font_mem_size / 2; */
1070 minsize = current_font_mem_size / 100 * percent_grow;
1071 if (size < minsize) size = minsize;
1072 if (size < initial_font_mem_size) size = initial_font_mem_size;
1074 for (k=0; k < MAXSPLITS; k++) {
1075 newsize = current_font_mem_size + size;
1076 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1077 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1078 n = (newsize + 1) * sizeof (fmemoryword);
1079 if (trace_flag) trace_memory("font_info", n);
1080 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1081 if (newfontinfo != NULL) break; /* did we get it ? */
1082 if (current_font_mem_size == 0) break; /* initial allocation must work */
1086 if (newfontinfo == NULL) {
1087 memory_error("font", n);
1088 return font_info; /* try and continue !!! */
1090 font_info = newfontinfo;
1092 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1093 show_line(log_line, 0);
1095 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1096 current_font_mem_size = newsize;
1097 if (trace_flag) probe_show(); /* 94/Mar/25 */
1102 #ifdef ALLOCATESTRING
1103 int current_pool_size=0;
1105 packed_ASCII_code *realloc_str_pool (int size)
1110 packed_ASCII_code *newstrpool=NULL;
1113 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1114 show_line(log_line, 0);
1116 if (current_pool_size == pool_size) {
1117 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1119 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1121 /* minsize = current_pool_size / 2; */
1122 minsize = current_pool_size / 100 * percent_grow;
1123 if (size < minsize) size = minsize;
1124 if (size < initial_pool_size) size = initial_pool_size;
1126 for (k = 0; k < MAXSPLITS; k++) {
1127 newsize = current_pool_size + size;
1128 if (newsize > pool_size) newsize = pool_size;
1129 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1130 n = (newsize + 1) * sizeof (packed_ASCII_code);
1131 if (trace_flag) trace_memory("str_pool", n);
1132 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1133 if (newstrpool != NULL) break; /* did we get it ? */
1134 if (current_pool_size == 0) break; /* initial allocation must work */
1135 size = size / 2; /* else can retry smaller */
1138 if (newstrpool == NULL) {
1139 memory_error("string pool", n);
1140 return str_pool; /* try and continue !!! */
1142 str_pool = newstrpool;
1143 update_statistics ((int) str_pool, n, current_pool_size);
1144 current_pool_size = newsize;
1146 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1147 show_line(log_line, 0);
1149 if (trace_flag) probe_show(); /* 94/Mar/25 */
1154 #ifdef ALLOCATESTRING
1155 int current_max_strings=0;
1157 pool_pointer *realloc_str_start (int size)
1162 pool_pointer *newstrstart=NULL;
1165 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1166 show_line(log_line, 0);
1168 if (current_max_strings == max_strings) {
1169 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1171 return str_start; /* pass it back to TeX 99/Fabe/4 */
1173 /* minsize = current_max_strings / 2; */
1174 minsize = current_max_strings / 100 * percent_grow;
1175 if (size < minsize) size = minsize;
1176 if (size < initial_max_strings) size = initial_max_strings;
1178 for (k = 0; k < MAXSPLITS; k++) {
1179 newsize = current_max_strings + size;
1180 if (newsize > max_strings) newsize = max_strings;
1181 /* important + 1 since str_start[maxstring + 1] originally */
1182 n = (newsize + 1) * sizeof (pool_pointer);
1183 if (trace_flag) trace_memory("str_start", n);
1184 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1185 if (newstrstart != NULL) break; /* did we get it ? */
1186 if (current_max_strings == 0) break; /* initial allocation must work */
1187 size = size / 2; /* otherwise can try smaller */
1190 if (newstrstart == NULL) {
1191 memory_error("string pointer", n);
1192 return str_start; /* try and continue */
1194 str_start = newstrstart;
1195 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1196 current_max_strings = newsize;
1198 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1199 show_line(log_line, 0);
1201 if (trace_flag) probe_show(); /* 94/Mar/25 */
1208 /* returns -1 if it fails */
1210 int allocate_ini (int size)
1211 { /* size == trie_size */
1212 int n, nl, no, nc, nr, nh, nt;
1213 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1214 no = (size + 1) * sizeof(trie_op_code);
1215 nc = (size + 1) * sizeof(packed_ASCII_code);
1216 /* nt = (size + 1) * sizeof(bool); */
1217 nt = (size + 1) * sizeof(char);
1218 n = nl + no + nc + nr + nh + nt;
1219 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1220 3 * sizeof(trie_pointer) + sizeof (char)); */
1221 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1222 trie_l = (trie_pointer *) malloc (roundup(nl));
1223 trie_o = (trie_op_code *) malloc (roundup(no));
1224 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1225 trie_r = (trie_pointer *) malloc (roundup(nr));
1226 trie_hash = (trie_pointer *) malloc (roundup(nh));
1227 /* trie_taken = (bool *) malloc (nt); */
1228 trie_taken = (char *) malloc (roundup(nt));
1229 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1230 trie_hash == NULL || trie_taken == NULL) {
1231 memory_error("iniTeX hyphen trie", n);
1232 // exit (1); /* serious error */
1236 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1237 trie_l, trie_o, trie_c);
1238 show_line(log_line, 0);
1239 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1240 trie_r, trie_hash, trie_taken);
1241 show_line(log_line, 0);
1243 update_statistics ((int) trie_l, nl, 0);
1244 update_statistics ((int) trie_o, no, 0);
1245 update_statistics ((int) trie_c, nc, 0);
1246 update_statistics ((int) trie_r, nr, 0);
1247 update_statistics ((int) trie_hash, nh, 0);
1248 update_statistics ((int) trie_taken, nt, 0);
1249 /* trie_size = size; */ /* ??? */
1250 if (trace_flag) probe_show(); /* 94/Mar/25 */
1251 return 0; // success
1255 #ifdef ALLOCATESAVESTACK
1256 int current_save_size=0;
1258 memory_word *realloc_save_stack (int size)
1262 memory_word *newsave_stack=NULL;
1265 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1266 show_line(log_line, 0);
1268 if (current_save_size == save_size) { /* arbitrary limit */
1269 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1271 return save_stack; /* let TeX handle the error */
1273 minsize = current_save_size / 100 * percent_grow;
1274 if (size < minsize) size = minsize;
1275 if (size < initial_save_size) size = initial_save_size;
1277 for (k = 0; k < MAXSPLITS; k++) {
1278 newsize = current_save_size + size;
1279 if (newsize > save_size) newsize = save_size;
1280 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1281 if (trace_flag) trace_memory("save_stack", n);
1282 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1283 if (newsave_stack != NULL) break; /* did we get it ? */
1284 if (current_save_size == 0) break; /* initial allocation must work */
1285 size = size / 2; /* else can retry smaller */
1288 if (newsave_stack == NULL) {
1289 memory_error("save stack", n);
1290 return save_stack; /* try and continue !!! */
1292 save_stack = newsave_stack;
1293 update_statistics ((int) save_stack, n, current_save_size);
1294 current_save_size = newsize;
1296 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1297 show_line(log_line, 0);
1298 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1299 show_line(log_line, 0);
1301 if (trace_flag) probe_show(); /* 94/Mar/25 */
1306 #ifdef ALLOCATEINPUTSTACK
1307 int current_stack_size=0; /* input stack size */
1309 in_state_record *realloc_input_stack (int size)
1313 in_state_record *newinputstack=NULL;
1316 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1317 show_line(log_line, 0);
1319 if (current_stack_size == stack_size) { /* arbitrary limit */
1320 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1324 minsize = current_stack_size / 100 * percent_grow;
1325 if (size < minsize) size = minsize;
1326 if (size < initial_stack_size) size = initial_stack_size;
1328 for (k = 0; k < MAXSPLITS; k++) {
1329 newsize = current_stack_size + size;
1330 if (newsize > stack_size) newsize = stack_size;
1331 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1332 if (trace_flag) trace_memory("input_stack", n);
1333 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1334 if (newinputstack != NULL) break; /* did we get it ? */
1335 if (current_stack_size == 0) break; /* initial allocation must work */
1336 size = size / 2; /* else can retry smaller */
1339 if (newinputstack == NULL) {
1340 memory_error("input stack", n);
1341 return input_stack; /* try and continue !!! */
1343 input_stack = newinputstack;
1344 update_statistics ((int) input_stack, n, current_stack_size);
1345 current_stack_size = newsize;
1347 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1348 show_line(log_line, 0);
1349 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1350 show_line(log_line, 0);
1352 if (trace_flag) probe_show(); /* 94/Mar/25 */
1357 #ifdef ALLOCATENESTSTACK
1358 int current_nest_size=0; /* current nest size */
1360 list_state_record *realloc_nest_stack (int size)
1364 list_state_record *newnest=NULL;
1367 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1368 show_line(log_line, 0);
1370 if (current_nest_size == nest_size) { /* arbitrary limit */
1371 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1373 return nest; /* let TeX handle the error */
1375 minsize = current_nest_size / 100 * percent_grow;
1376 if (size < minsize) size = minsize;
1377 if (size < initial_nest_size) size = initial_nest_size;
1379 for (k = 0; k < MAXSPLITS; k++) {
1380 newsize = current_nest_size + size;
1381 if (newsize > nest_size) newsize = nest_size;
1382 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1383 if (trace_flag) trace_memory("nest stack", n);
1384 newnest = (list_state_record *) REALLOC (nest, n);
1385 if (newnest != NULL) break; /* did we get it ? */
1386 if (current_nest_size == 0) break; /* initial allocation must work */
1387 size = size / 2; /* else can retry smaller */
1390 if (newnest == NULL) {
1391 memory_error("nest stack", n);
1392 return nest; /* try and continue !!! */
1395 update_statistics ((int) nest, n, current_nest_size);
1396 current_nest_size = newsize;
1398 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1399 show_line(log_line, 0);
1400 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1401 show_line(log_line, 0);
1403 if (trace_flag) probe_show(); /* 94/Mar/25 */
1408 #ifdef ALLOCATEPARAMSTACK
1409 int current_param_size=0; /* current param size */
1411 halfword *realloc_param_stack (int size)
1415 halfword *newparam=NULL;
1418 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1419 show_line(log_line, 0);
1421 if (current_param_size == param_size) { /* arbitrary limit */
1422 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1424 return param_stack; /* let TeX handle the error */
1426 minsize = current_param_size / 100 * percent_grow;
1427 if (size < minsize) size = minsize;
1428 if (size < initial_param_size) size = initial_param_size;
1430 for (k = 0; k < MAXSPLITS; k++) {
1431 newsize = current_param_size + size;
1432 if (newsize > param_size) newsize = param_size;
1433 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1434 if (trace_flag) trace_memory("param stack", n);
1435 newparam = (halfword *) REALLOC (param_stack, n);
1436 if (newparam != NULL) break; /* did we get it ? */
1437 if (current_param_size == 0) break; /* initial allocation must work */
1438 size = size / 2; /* else can retry smaller */
1441 if (newparam == NULL) {
1442 memory_error("param stack", n);
1443 return param_stack; /* try and continue !!! */
1445 param_stack = newparam;
1446 update_statistics ((int) param_stack, n, current_param_size);
1447 current_param_size = newsize;
1449 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1450 show_line(log_line, 0);
1451 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1452 show_line(log_line, 0);
1454 if (trace_flag) probe_show(); /* 94/Mar/25 */
1459 #ifdef ALLOCATEBUFFER
1460 int current_buf_size=0;
1462 ASCII_code *realloc_buffer (int size)
1466 ASCII_code *newbuffer=NULL;
1469 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1470 show_line(log_line, 0);
1472 if (current_buf_size == buf_size) { /* arbitrary limit */
1473 /* memory_error ("buffer", buf_size); */
1475 return buffer; /* pass it back to TeX 99/Fabe/4 */
1477 minsize = current_buf_size / 100 * percent_grow;
1478 if (size < minsize) size = minsize;
1479 if (size < initial_buf_size) size = initial_buf_size;
1481 for (k = 0; k < MAXSPLITS; k++) {
1482 newsize = current_buf_size + size;
1483 if (newsize > buf_size) newsize = buf_size;
1484 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1485 if (trace_flag) trace_memory("buffer", n);
1486 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1487 if (newbuffer != NULL) break; /* did we get it ? */
1488 if (current_buf_size == 0) break; /* initial allocation must work */
1489 size = size / 2; /* else can retry smaller */
1492 if (newbuffer == NULL) {
1493 memory_error("buffer", n);
1494 return buffer; /* try and continue !!! */
1497 update_statistics ((int) buffer, n, current_buf_size);
1499 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1501 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1503 current_buf_size = newsize;
1505 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1506 show_line(log_line, 0);
1507 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1508 show_line(log_line, 0);
1510 if (trace_flag) probe_show(); /* 94/Mar/25 */
1515 /* we used to allocate this one only to reduce the size of the PE file */
1516 /* not used anymore - NO advantage */
1518 #ifdef ALLOCATEDVIBUF
1519 eight_bits *allocatedvibuf (int size)
1521 eight_bits *dvi_buf;
1524 n = (size + 1) * sizeof(eight_bits);
1525 if (trace_flag) trace_memory("dvi_buf", n);
1526 dvi_buf = (eight_bits *) malloc (roundup(n));
1527 if (dvi_buf == NULL) {
1528 memory_error("dvi_buf", n);
1532 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1533 show_line(log_line, 0);
1535 update_statistics ((int) dvi_buf, n, 0);
1536 if (trace_flag) probe_show(); /* 94/Mar/25 */
1541 /* we used to allocate this one only to reduce the size of the PE file */
1542 /* it can be done without loss in performance, since register eqtb = zeqtb */
1543 #ifdef ALLOCATEZEQTB
1544 memory_word *allocatezeqtb (int k)
1549 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1550 if (trace_flag) trace_memory("eqtb", n);
1551 zeqtb = (memory_word *) malloc (roundup(n));
1552 if (zeqtb == NULL) {
1553 memory_error("eqtb", n);
1554 // exit (1); /* serious error */
1558 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1559 show_line(log_line, 0);
1561 update_statistics ((int) zeqtb, n, 0);
1562 if (trace_flag) probe_show(); /* 94/Mar/25 */
1567 /* here is the main memory allocation routine -- calls the above */
1568 /* returns -1 if it fails */
1570 int allocate_memory (void)
1571 { /* allocate rather than static 93/Nov/26 */
1574 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1578 #error ERROR: Not ready for ALLOCATEHASH...
1581 /* probably not worth while/not a good idea allocating following */
1582 /* they are all rather small, and typically don't need expansion */
1583 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1585 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1586 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1587 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1589 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1591 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1593 if (trace_flag) trace_memory("hash table", n);
1595 zzzae = (htwohalves *) malloc (roundup(n));
1597 zzzae = (twohalves *) malloc (roundup(n));
1599 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1600 if (zzzae == NULL) {
1601 memory_error("hash table", n);
1602 // exit (1); /* serious error */
1603 return -1; /* serious error */
1606 n = (inputsize + 1) * sizeof(memory_word);
1607 if (trace_flag) trace_memory("input_stack", n);
1608 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1609 input_stack = (memory_word *) malloc (roundup(n));
1610 if (input_stack == NULL) {
1611 memory_error("input_stack", n);
1612 // exit (1); /* serious error */
1613 return -1; /* serious error */
1617 /* no real reason to allocate dvi_buf - no need to ever grow it */
1618 #ifdef ALLOCATEDVIBUF
1619 /* zdvibuf = NULL; */
1620 zdvibuf = allocatedvibuf (dvi_buf_size);
1621 if (zdvibuf == NULL) return -1;
1624 #ifdef ALLOCATEZEQTB
1626 #ifdef INCREASEFONTS
1627 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1628 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1630 /* zeqtb = allocatezeqtb (13507); */
1631 zeqtb = allocatezeqtb (hash_size + 4007);
1635 #ifdef ALLOCATEINPUTSTACK
1636 input_stack = NULL; /* new 1999/Jan/21 */
1637 current_stack_size = 0;
1638 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1641 #ifdef ALLOCATENESTSTACK
1642 nest = NULL; /* new 1999/Jan/21 */
1643 current_nest_size = 0;
1644 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1647 #ifdef ALLOCATEPARAMSTACK
1648 param_stack = NULL; /* new 1999/Jan/21 */
1649 current_param_size = 0;
1650 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1653 #ifdef ALLOCATESAVESTACK
1654 save_stack = NULL; /* new 1999/Jan/7 */
1655 current_save_size = 0;
1656 save_stack = realloc_save_stack (initial_save_size);
1660 buffer = NULL; /* need to do earlier */
1661 current_buf_size = 0;
1662 buffer = realloc_buffer (initial_buf_size);
1665 #ifdef ALLOCATESTRING
1667 current_pool_size = 0;
1669 current_max_strings = 0;
1670 /* need to create space because iniTeX writes in before reading pool file */
1671 /* for a start, puts in strings for 256 characters */
1672 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1674 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1675 str_pool = realloc_str_pool (initial_pool_size);
1676 str_start = realloc_str_start (initial_max_strings);
1680 /* the following can save a lot of the usual 800k fixed allocation */
1683 current_font_mem_size = 0;
1684 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1685 /* if ini-TeX we need to do it here - no format file read later */
1686 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1692 mem_min = mem_bot; /* just to avoid complaints in texbody */
1693 mem_top = mem_initex;
1695 /* allocate main memory here if this is iniTeX */
1696 /* otherwise wait for format undumping in itex.c ... */
1698 /* avoid this if format specified on command line ??? */
1699 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1700 mem = allocate_main_memory(mem_initex); /* made variable ! */
1703 return -1; /* serious error */
1707 /* now for the hyphenation exception stuff */
1708 #ifdef ALLOCATEHYPHEN
1711 /* this will be overridden later by what is in format file */
1712 hyphen_prime = default_hyphen_prime;
1713 /* non ini-TeX use assumes format will be read and that specifies size */
1715 if (new_hyphen_prime) hyphen_prime = new_hyphen_prime;
1716 if (realloc_hyphen (hyphen_prime)) /* allocate just in case no format */
1721 /* now for memory for the part of the hyphenation stuff that always needed */
1722 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1723 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1724 #ifdef ALLOCATETRIES
1726 if (allocate_tries (trie_size)) return -1;
1730 /* now for memory for hyphenation stuff needed only when running iniTeX */
1733 if (allocate_ini(trie_size)) return -1;
1736 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1737 trie_c = NULL; /* (trie_size + 1) * char */
1738 trie_taken = NULL; /* (trie_size + 1) * bool */
1742 free(holeadr); /* create the hole */
1744 return 0; // success
1747 /* returns non-zero if error - done to test integrity of stack mostly */
1749 int free_memory (void)
1750 { /* free in reverse order 93/Nov/26 */
1752 unsigned heaptotal=0;
1753 /* unsigned total; */
1755 if (trace_flag) show_line("free_memory ", 0);
1758 if (debug_flag) check_eqtb("free_memory");
1760 if (verbose_flag || trace_flag) show_maximums(stdout);
1762 if (heap_flag) (void) heap_dump(stdout, 1);
1766 heaptotal = (void) heap_dump(stdout, 0);
1768 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1769 heaptotal, max_address);
1770 show_line(log_line, 0);
1773 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1774 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1775 show_line(log_line, 0);
1777 /* following only needed to check consistency of heap ... useful debugging */
1778 if (trace_flag) show_line("Freeing memory again\n", 0);
1781 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1783 /* the following checks the heap integrity */
1785 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1787 #ifdef SHOWHEAPERROR
1789 if (n != _HEAPOK) { /* 94/Feb/18 */
1790 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1791 show_line(log_line, 1);
1792 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1793 show_line(log_line, 0);
1794 return n; /* non-zero and negative */ /* unreachable ??? */
1797 /* only free memory if safe ... additional check */
1800 if (trie_taken != NULL) free(trie_taken);
1801 if (trie_hash != NULL) free(trie_hash);
1802 if (trie_r != NULL) free(trie_r);
1803 if (trie_c != NULL) free(trie_c);
1804 if (trie_o != NULL) free(trie_o);
1805 if (trie_l != NULL) free(trie_l);
1807 trie_hash = trie_l = trie_r = NULL;
1812 #ifdef ALLOCATETRIES
1813 if (trie_trc != NULL) free (trie_trc);
1814 if (trie_tro != NULL) free (trie_tro);
1815 if (trie_trl != NULL) free (trie_trl);
1817 trie_tro = trie_trl = NULL;
1819 #ifdef ALLOCATEHYPHEN
1820 if (hyph_list != NULL) free(hyph_list);
1821 if (hyph_word != NULL) free(hyph_word);
1826 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1827 if (mainmemory != NULL) free(mainmemory);
1831 if (font_info != NULL) free(font_info);
1834 #ifdef ALLOCATESTRING
1835 if (str_start != NULL) free(str_start);
1836 if (str_pool != NULL) free(str_pool);
1842 if (zzzae != NULL) free(zzzae);
1846 #ifdef ALLOCATEDVIBUF
1847 if (zdvibuf != NULL) free(zdvibuf);
1850 #ifdef ALLOCATEZEQTB
1851 if (zeqtb != NULL) free(zeqtb);
1855 #ifdef ALLOCATEPARAMSTACK
1856 if (param_stack != NULL) free(param_stack);
1859 #ifdef ALLOCATENESTSTACK
1860 if (nest != NULL) free(nest);
1863 #ifdef ALLOCATEINPUTSTACK
1864 if (input_stack != NULL) free(input_stack);
1867 #ifdef ALLOCATESAVESTACK
1868 if (save_stack != NULL) free(save_stack);
1871 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1872 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1873 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1874 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1875 format_file = string_file = source_direct = NULL;
1876 if (dvi_file_name != NULL) free(dvi_file_name);
1877 if (log_file_name != NULL) free(log_file_name);
1878 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1885 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1886 if (x % 2 == 0) return false;
1887 for (k = 3; k < x; k = k + 2) {
1888 if (x % k == 0) return false;
1889 /* if (k * k > x) return true; */
1890 if (sum * 4 > x) return true;
1897 bool show_use=false;
1898 bool floating=false;
1900 void complainarg (int c, char *s)
1902 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1903 show_line(log_line, 1);
1904 show_use = 1; // 2000 June 21
1907 /* following is list of allowed command line flags and args */
1909 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1911 /* only 01234567.9 still left to take ... maybe recycle u */
1913 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1915 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1917 void reorderargs (int ac, char **av)
1918 { /* put in 1993/Dec/28 */
1921 // char takeargs[128]; /* large enough for all command line arg chars */
1922 char takeargs[256]; /* large enough for all command line arg chars */
1924 /* assumes arg pointers av[] are writeable */
1925 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1927 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1928 /* show_line("No arguments?\n", 0); */ /* debugging */
1929 return; /* no args ! */
1933 t = takeargs; /* list of those that take args */
1934 while (*s != '\0' && *(s+1) != '\0') {
1935 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1940 show_line(takeargs, 0);
1945 for (;;) { /* scan to end of command line args */
1946 if (*av[n] != '-') break;
1947 /* does it take an argument ? and is this argument next ? */
1949 *(av[n]+2) == '\0' &&
1950 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1951 strchr(takeargs, *(av[n]+1)) != NULL)
1952 n += 2; /* step over it */
1957 for (;;) { /* look for more command line args */
1960 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
1961 while (m < ac && *av[m] != '-') m++; /* first command */
1963 /* does it take an argument ? and is this argument next ? */
1964 /* check first whether the `-x' is isolated, or arg follows directly */
1965 /* then check whether this is one of those that takes an argument */
1967 *(av[m]+2) == '\0' &&
1968 strchr(takeargs, *(av[m]+1)) != NULL) {
1969 s = av[m]; /* move command down before non-command */
1971 for (; m > n; m--) av[m+1] = av[m-1];
1974 n += 2; /* step over moved args */
1977 s = av[m]; /* move command down before non-command */
1978 for (; m > n; m--) av[m] = av[m-1];
1980 n++; /* step over moved args */
1985 int test_align (int address, int size, char *name)
1988 if (size > 4) n = address % 4;
1989 else n = address % size;
1991 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
1992 show_line(log_line, 0);
1997 /* activate detailed checking of alignment when trace_flag is set */
1999 void check_fixed_align (int flag)
2001 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2002 show_line("PLEASE RECOMPILE ME!\n", 1);
2004 #ifdef CHECKALIGNMENT
2006 test_align ((int) &mem_top, 4, "mem_top");
2007 test_align ((int) &mem_max, 4, "mem_max");
2008 test_align ((int) &mem_min, 4, "mem_min");
2009 test_align ((int) &bad, 4, "bad");
2010 test_align ((int) &trie_size, 4, "trie_size");
2011 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2012 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2013 test_align ((int) &name_length, 4, "name_length");
2014 test_align ((int) &first, 4, "first");
2015 test_align ((int) &last, 4, "last");
2016 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2017 test_align ((int) &pool_ptr, 4, "pool_ptr");
2018 test_align ((int) &str_ptr, 4, "str_ptr");
2019 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2020 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2021 test_align ((int) &log_file, 4, "log_file");
2022 test_align ((int) &tally, 4, "tally");
2023 test_align ((int) &term_offset, 4, "term_offset");
2024 test_align ((int) &file_offset, 4, "file_offset");
2025 test_align ((int) &trick_count, 4, "trick_count");
2026 test_align ((int) &first_count, 4, "first_count");
2027 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2028 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2029 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2030 test_align ((int) &use_err_help, 4, "use_err_help");
2031 test_align ((int) &interrupt, 4, "interrupt");
2032 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2033 test_align ((int) &arith_error, 4, "arith_error");
2034 test_align ((int) &tex_remainder, 4, "tex_remainder");
2035 test_align ((int) &temp_ptr, 4, "temp_ptr");
2036 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2037 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2038 test_align ((int) &var_used, 4, "var_used");
2039 test_align ((int) &dyn_used, 4, "dyn_used");
2040 test_align ((int) &avail, 4, "avail");
2041 test_align ((int) &mem_end, 4, "mem_end");
2042 test_align ((int) &mem_start, 4, "mem_start");
2043 test_align ((int) &rover, 4, "rover");
2044 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2045 test_align ((int) &depth_threshold, 4, "depth_threshold");
2046 test_align ((int) &breadth_max, 4, "breadth_max");
2047 test_align ((int) &nest, sizeof(nest[0]), "nest");
2050 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2052 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2053 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2054 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2055 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2057 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2058 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2059 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2060 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2061 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2062 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2063 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2064 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2066 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2067 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2068 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2069 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2070 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2071 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2072 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2073 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2074 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2075 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2076 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2077 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2078 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2079 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2080 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2081 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2082 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2083 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2084 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2085 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2086 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2087 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2088 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2089 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2091 #ifdef ALLOCATEDVIBUF
2092 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2094 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2095 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2096 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2097 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2098 test_align ((int) &background, sizeof(background[0]), "background");
2099 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2100 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2101 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2102 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2103 test_align ((int) &hc, sizeof(hc[0]), "hc");
2104 test_align ((int) &hu, sizeof(hu[0]), "hu");
2105 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2106 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2108 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2109 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2110 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2111 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2113 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2114 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2115 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2116 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2117 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2119 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2120 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2121 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2122 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2126 void check_alloc_align (int flag) {
2127 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2128 show_line("PLEASE RECOMPILE ME!\n", 1);
2129 #ifdef CHECKALIGNMENT
2132 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2134 #ifndef ALLOCATEDVIBUF
2135 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2137 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2138 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2139 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2140 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2141 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2142 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2143 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2144 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2145 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2146 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2147 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2148 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2149 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2150 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2151 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2156 void showaddresses (void)
2160 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2161 show_line(log_line, 0);
2162 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2163 show_line(log_line, 0);
2164 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2165 show_line(log_line, 0);
2166 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2167 save_stack, input_stack, line_stack, param_stack);
2168 show_line(log_line, 0);
2169 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2170 font_check, font_size, font_dsize, font_params, font_name);
2171 show_line(log_line, 0);
2172 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2173 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2174 show_line(log_line, 0);
2178 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2180 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2181 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2183 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2184 bool backwardflag = false; /* don't cripple all advanced features */
2185 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2186 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2187 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2188 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2189 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2190 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2191 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2192 bool workingdirectory = false; /* if working directory set in ini */
2193 /* set up full file name for dviwindo.ini and check for [Environment] */
2195 bool setupdviwindo (void)
2196 { /* set up full file name for dviwindo.ini */
2197 char dviwindoini[PATH_MAX];
2198 char line[PATH_MAX];
2201 int em = strlen(envsection);
2202 int wm = strlen(wndsection);
2203 int dm = strlen(workdirect);
2207 /* Easy to find Windows directory if Windows runs */
2208 /* Or if user kindly set WINDIR environment variable */
2209 /* Or if running in Windows NT */
2210 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2211 (windir = getenv("WINDIR")) != NULL ||
2212 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2213 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2214 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2215 strcpy(dviwindoini, windir);
2216 strcat(dviwindoini, "\\");
2217 strcat(dviwindoini, inifilename);
2218 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2221 _searchenv (inifilename, "PATH", dviwindoini);
2222 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2225 wndflag = envflag = 0;
2226 /* workingdirectory = false; */
2227 if (*dviwindoini != '\0') {
2228 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2229 /* check whether dviwindo.ini actually has [Environment] section */
2230 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2231 else pinput = _fsopen(dviwindo, "r", share_flag);
2232 if (pinput != NULL) {
2233 while (fgets (line, sizeof(line), pinput) != NULL) {
2234 if (*line == ';') continue;
2235 if (*line == '\n') continue;
2237 if (wndflag && envflag) break; /* escape early */
2239 if (_strnicmp(line, wndsection, wm) == 0) {
2241 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2242 show_line(log_line, 0);
2246 else if (_strnicmp(line, envsection, em) == 0) {
2248 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2249 show_line(log_line, 0);
2251 /* fclose(input); */
2254 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2256 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2257 show_line(log_line, 0);
2259 workingdirectory = true;
2263 (void) fclose(pinput);
2267 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2268 (void) fclose(pinput);
2270 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2271 strcpy(dviwindo, ""); /* failed, for one reason or another */
2276 /* cache to prevent allocating twice in a row */
2278 char *lastname=NULL, *lastvalue=NULL;
2280 /* get value of env var - try first in dviwindo.ini then DOS env */
2281 /* returns allocated string -- these strings are not freed again */
2282 /* is it safe to do that now ? 98/Jan/31 */
2283 char *grabenv (char *varname)
2285 char line[PATH_MAX];
2289 /* int m = strlen(envsection); */
2290 /* int n = strlen(varname); */
2292 if (varname == NULL) return NULL; /* sanity check */
2293 if (*varname == '\0') return NULL; /* sanity check */
2294 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2295 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2296 if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2298 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2299 show_line(log_line, 0);
2301 /* return lastvalue; */ /* save some time here */
2302 return xstrdup(lastvalue);
2303 /* duplicate so can free safely 98/Jan/31 */
2306 /* hmm, following was not xstrdup(...) */ /* not cached */
2307 if (usedviwindo == 0 || *dviwindo == '\0') {
2308 /* return getenv(varname); */
2309 s = getenv(varname);
2310 if (s == NULL) return NULL;
2311 else return xstrdup(s); /* make safe 98/Jan/31 */
2314 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2315 else pinput = _fsopen(dviwindo, "r", share_flag);
2317 if (pinput != NULL) {
2318 m = strlen(envsection);
2319 /* search for [Environment] section */ /* should be case insensitive */
2320 while (fgets (line, sizeof(line), pinput) != NULL) {
2321 if (*line == ';') continue;
2322 if (*line == '\n') continue;
2323 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2324 /* search for varname=... */ /* should be case sensitive ? */
2325 n = strlen(varname);
2326 while (fgets (line, sizeof(line), pinput) != NULL) {
2327 if (*line == ';') continue;
2328 if (*line == '[') break;
2329 /* if (*line == '\n') break; */ /* ??? */
2330 if (*line <= ' ') continue; /* 95/June/23 */
2331 /* if (strncmp(line, varname, n) == 0 && */
2332 if (_strnicmp(line, varname, n) == 0 &&
2333 *(line+n) == '=') { /* found it ? */
2334 (void) fclose (pinput);
2335 /* flush trailing white space */
2336 s = line + strlen(line) - 1;
2337 while (*s <= ' ' && s > line) *s-- = '\0';
2338 if (trace_flag) { /* DEBUGGING ONLY */
2339 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2340 show_line(log_line, 0);
2343 if (lastname != NULL) free(lastname);
2344 lastname = xstrdup (varname);
2345 if (lastvalue != NULL) free(lastvalue);
2346 lastvalue = xstrdup(s);
2347 return xstrdup(s); /* 98/Jan/31 */
2348 } /* end of matching varname */
2349 } /* end of while fgets */
2350 /* break; */ /* ? not found in designated section */
2351 } /* end of search for [Environment] section */
2353 (void) fclose (pinput);
2354 } /* end of if fopen */
2355 s = getenv(varname); /* failed, so try and get from environment */
2356 /* if (s != NULL) return s; */
2358 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2359 if (lastname != NULL) free(lastname);
2360 lastname = xstrdup (varname);
2361 if (lastvalue != NULL) free(lastvalue);
2362 lastvalue = xstrdup(s); /* remember in case asked again ... */
2364 return xstrdup(s); /* 98/Jan/31 */
2366 else return NULL; /* return NULL if not found anywhere */
2369 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2371 void flush_trailing_slash (char *directory)
2374 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2375 if (strcmp(directory, "") != 0) {
2376 s = directory + strlen(directory) - 1;
2377 if (*s == '\\' || *s == '/') *s = '\0';
2381 void knuthify (void)
2383 /* show_current = false; */ /* show ultimate limits */
2384 /* reorder_arg_flag = false; */ /* don't reorder command line */
2385 /* deslash = false; */ /* don't unixify file names */
2386 /* return_flag = false; */ /* don't allow just ^^M termination */
2387 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2388 restrict_to_ascii = false; /* don't complain non ASCII */
2389 allow_patterns = false; /* don't allow pattern redefinition */
2390 show_in_hex = true; /* show character code in hex */
2391 show_in_dos = false; /* redundant with previous */
2392 show_numeric = false; /* don't show character code decimal */
2393 show_missing = false; /* don't show missing characters */
2394 civilize_flag = false; /* don't reorder date fields */
2395 c_style_flag = false; /* don't add file name to error msg */
2396 show_fmt_flag = false; /* don't show format file in log */
2397 show_tfm_flag = false; /* don't show metric file in log */
2398 /* font_max = 255; */ /* revert to TeX 82 limit */
2399 /* if you want this, change in tex.h definition of font_max to `int' */
2400 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2402 show_line_break_stats = false; /* do not show line break stats */
2403 show_fonts_used = false;
2404 default_rule = 26214; /* revert to default rule thickness */
2405 pseudo_tilde = false;
2406 pseudo_space = false;
2407 show_texinput_flag = false;
2408 truncate_long_lines = false;
2409 allow_quoted_names = false;
2410 show_cs_names = false;
2411 font_dimen_zero = false; /* 98/Oct/5 */
2412 ignore_frozen = false; /* 98/Oct/5 */
2413 suppress_f_ligs = false; /* 99/Jan/5 */
2414 full_file_name_flag = false; // 00 Jun 18
2415 save_strings_flag = false; // 00 Aug 15
2416 knuth_flag = true; /* so other code can know about this */
2417 } /* end of knuthify */
2419 /* following have already been used up */
2421 /* abcdefghijklmnopqrstuvwxyz */
2423 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2427 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2429 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2431 /* following made global so analyze_flag can be made separate procedure */
2433 // char *xchrfile=""; /* save space use xstrdup */
2434 char *xchrfile = NULL; /* save space use xstrdup */
2435 // char *replfile="";/* save space use xstrdup */
2436 char *replfile = NULL;/* save space use xstrdup */
2438 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2440 /* analyze command line flag or argument */
2441 /* c is the flag letter itself, while optarg is start of arg if any */
2443 /* when making changes, revise allowedargs */
2446 int analyze_flag (int c, char *optarg)
2450 want_version = true;
2451 verbose_flag = true;
2457 interaction = batch_mode; /* quiet mode */
2460 interaction = nonstop_mode; /* run mode */
2463 interaction = scroll_mode; /* scroll mode */
2466 interaction = error_stop_mode; /* tex mode */
2469 backwardflag = true; /* 94/Jun/15 */
2470 knuthify(); /* revert to `standard' Knuth TeX */
2473 c_style_flag = true; /* C style error msg 94/Mar/21 */
2476 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2479 current_tfm = false; /* not look current dir for TFM */
2482 current_flag = false; /* not look current dir for files */
2485 show_missing = false; /* do not show missing 94/June/10 */
2488 deslash = false; /* flipped 93/Nov/18 */
2489 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2492 allow_patterns = true; /* 93/Nov/26 */
2493 /* reset_exceptions = true; */ /* 93/Dec/23 */
2495 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2497 show_in_hex = true; /* flipped 00/Jun/18 */
2500 show_in_dos = true; /* 96/Jan/26 */
2503 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2506 workingdirectory = true; /* use source dir 98/Sep/29 */
2509 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2512 show_fonts_used = false; /* 97/Dec/24 */
2515 shorten_file_name = true; /* 95/Feb/20 */
2518 show_cs_names = true; /* 98/Mar/31 */
2521 ignore_frozen = true; /* 98/Oct/5 */
2524 font_dimen_zero = false; /* 98/Oct/5 */
2527 show_texinput_flag = false; /* 98/Jan/28 */
2529 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2532 usedviwindo = false; /* 94/May/19 */
2535 show_line_break_stats = false; /* 96/Feb/8 */
2538 show_fmt_flag = false; /* 94/Jun/21 */
2541 format_specific = false; /* 95/Jan/7 */
2544 encoding_specific = false; /* 98/Oct/5 */
2547 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2549 /* following are pretty obscure */
2550 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2552 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2554 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2557 full_file_name_flag = false; // 00 Jun 18
2560 save_strings_flag = false; // 00 Aug 15
2562 /* following are unannounced options */ /* some may be recycled ... */
2567 quitflag++; /* 93/Dec/16 */
2569 /* The following are really obscure and should not be advertized */
2571 show_current = false; /* tex8 93/Dec/14 */
2574 show_numeric = false; /* 93/Dec/21 */
2577 civilize_flag = false; /* 93/Dec/16 */
2580 open_trace_flag = true; /* openinou 1994/Jan/8 */
2583 reorder_arg_flag = false; /* local */
2586 test_dir_access = false; /* 94/Feb/10 */
2589 dir_method = false; /* 94/Feb/10 */
2592 file_method = false; /* 94/Feb/13 */
2594 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2595 /* case 'X': nohandler++; break; */
2596 /* case 'f': waitflush = false; break; */
2597 /* case 'F': floating = true; break; */
2598 /* *********** following command line options take arguments ************** */
2601 mem_initex = mem_top;
2603 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2604 if (mem_initex == 0)
2605 complainarg(c, optarg);
2608 #ifdef VARIABLETRIESIZE
2611 trie_size = default_trie_size;
2613 trie_size = atoi(optarg); /* 93 Dec/1 */
2615 complainarg(c, optarg);
2618 #ifdef ALLOCATEHYPHEN
2621 new_hyphen_prime = hyphen_prime * 2;
2623 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2624 if (new_hyphen_prime == 0)
2625 complainarg(c, optarg);
2628 #ifdef ALLOCATEDVIBUF
2631 dvi_buf_size = default_dvi_buf_size;
2633 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2634 if (dvi_buf_size == 0)
2635 complainarg(c, optarg);
2642 percent_grow = atoi(optarg); /* 93/Dec/11 */
2643 if (percent_grow == 0)
2644 complainarg(c, optarg);
2650 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2651 if (pseudo_tilde > 255)
2653 else if (pseudo_tilde < 128)
2656 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2657 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2663 tab_step = atoi(optarg); /* 94/July/3 */
2665 complainarg(c, optarg);
2669 xchrfile = xstrdup("xchr.map");
2671 xchrfile = xstrdup(optarg);
2672 if (xchrfile == NULL || *xchrfile == '\0')
2673 complainarg(c, optarg);
2677 replfile = xstrdup("repl.key");
2679 replfile = xstrdup(optarg);
2680 if (replfile == NULL || *replfile == '\0')
2681 complainarg(c, optarg);
2683 /* more obscure stuff - ppssibly recycle */
2686 default_rule = 26214; /* 95/Oct/9 */
2688 default_rule = atoi(optarg); /* 95/Oct/9 */
2689 if (default_rule == 0)
2690 complainarg(c, optarg);
2696 complainarg(c, optarg);
2702 dvi_directory = xstrdup(optarg);
2703 if (strcmp(dvi_directory, "") == 0)
2704 complainarg(c, optarg);
2710 log_directory = xstrdup(optarg);
2711 if (strcmp(log_directory, "") == 0)
2712 complainarg(c, optarg);
2718 aux_directory = xstrdup(optarg);
2719 if (strcmp(aux_directory, "") == 0)
2720 complainarg(c, optarg);
2725 return -1; // failed to recognize
2731 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2732 //char *yytexcmd="yandytex.cmd";
2733 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2735 /* Try and read default command file - YANDYTEX.CMD */
2736 /* in current directory and then in directory of YANDYTEX */
2737 /* (does not make sense in TeX file directory) */
2738 /* since we don't yet know where that is ! */
2739 /* can't conveniently include this in output file either - not open yet */
2741 /* used both for yytex.cmd and @ indirect command line files */
2742 /* can this be reentered ? */
2744 /* supply extension if none */
2745 void yy_extension (char *fname, char *ext)
2748 if ((s = strrchr(fname, '.')) == NULL ||
2749 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2755 /* remove file name - keep only path - inserts '\0' to terminate */
2757 void strip_name (char *pathname)
2760 if ((s = strrchr(pathname, '\\')) != NULL);
2761 else if ((s = strrchr(pathname, '/')) != NULL);
2762 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2767 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2769 char *programpath = ""; /* pathname of program */
2770 /* redundant with texpath ? */
2772 /* The following does not deslashify arguments ? Do we need to ? */
2774 int read_commands (char *filename)
2776 char commandfile[PATH_MAX];
2778 char line[PATH_MAX];
2779 char *linedup; /* need to copy line to preserve args */
2785 /* Try first in current directory (or use full name as specified) */
2786 strcpy(commandfile, filename);
2787 yy_extension(commandfile, "cmd");
2788 if (share_flag == 0)
2789 command = fopen(commandfile, "r");
2791 command = _fsopen(commandfile, "r", share_flag);
2792 if (command == NULL) {
2793 /* If that fails, try in YANDYTeX program directory */
2794 strcpy(commandfile, programpath);
2795 /* don't need fancy footwork, since programpath non-empty */
2796 strcat(commandfile, "\\");
2797 strcat(commandfile, filename);
2798 yy_extension(commandfile, "cmd");
2799 if (share_flag == 0)
2800 command = fopen(commandfile, "r");
2802 command = _fsopen(commandfile, "r", share_flag);
2803 if (command == NULL) {
2804 /* perrormod(commandfile); */ /* debugging only */
2805 /* strcpy(commandfile, ""); */ /* indicate failed */
2806 return 0; /* no command line file YYTEX.CMD */
2810 /* allow for multiple lines --- ignore args that don't start with `-' */
2811 while (fgets(line, PATH_MAX, command) != NULL) {
2812 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2813 /* skip over comment lines and blank lines */
2814 if (*line == '%' || *line == ';' || *line == '\n') continue;
2815 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2816 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2817 linedup = xstrdup (line); /* 93/Nov/15 */
2818 if (linedup == NULL) {
2819 show_line("ERROR: out of memory\n", 1); /* read_commands */
2821 return -1; // failure
2823 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2825 if (*s == '-' || *s == '/') {
2828 /* if (*optarg = '=') optarg++; */
2829 if (*optarg == '=') optarg++;
2830 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2832 /* else break; */ /* ignore non-flag items */
2833 s = strtok(NULL, " \t\n\r"); /* go to next token */
2835 /* If you want to see command lines in file - put -v in the file */
2836 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2838 (void) fclose(command); /* no longer needed */
2839 return 1; // success
2842 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2844 /* try and read commands on command line */
2845 int read_command_line (int ac, char **av)
2848 char *optargnew; /* equal to optarg, unless that starts with `=' */
2849 /* in which case it is optarg+1 to step over the `=' */
2850 /* if optarg = 0, then optargnew = 0 also */
2852 // show_line("read_command_line\n", 0);
2853 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2855 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2856 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2857 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2858 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2859 if (optarg != 0 && *optarg == '=')
2860 optargnew = optarg+1;
2863 analyze_flag (c, optargnew);
2865 if (show_use || quitflag == 3) {
2866 // showversion (stdout);
2868 strcat(log_line, "\n");
2869 show_line(log_line, 0);
2870 stampcopy(log_line);
2871 strcat(log_line, "\n");
2872 show_line(log_line, 0);
2873 if (show_use) show_usage(av[0]);
2874 else if (quitflag == 3) {
2875 strcat(log_line, "\n");
2876 show_line(log_line, 0);
2879 return -1; // failure
2882 if (floating) testfloating(); /* debugging */
2885 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2886 if (read_xchr_file(replfile, 1, av)) {
2887 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2891 /* key_replace used in texmf.c (input_line) */
2892 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2893 if (read_xchr_file(xchrfile, 0, av)) {
2894 if (trace_flag) show_line("NON ASCII ON\n", 0);
2898 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2899 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2904 void uppercase (char *s)
2907 while ((c = *s) != '\0') {
2908 /* if (islower(c)) *s = toupper (*s); */
2915 int init_commands (int ac, char **av)
2917 /* NOTE: some defaults changed 1993/Nov/18 */
2918 /* want_version = show_use = switchflag = return_flag = false;
2919 is_initex = trace_flag = deslash = non_ascii = false; */
2920 is_initex = false; /* check for dumping format file */
2921 allow_patterns = false; /* using \pattern after format file loaded */
2922 reset_exceptions = false;
2924 key_replace = false;
2925 want_version = false;
2926 open_trace_flag = false;
2928 verbose_flag = false;
2930 restrict_to_ascii = false;
2931 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2932 show_in_dos = false; /* default is not to translate to DOS 850 */
2933 return_flag = true; // hard wired now
2934 trimeof = true; // hard wired now
2936 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2937 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2938 default_rule = 26214; /* default rule variable 95/Oct/9 */
2939 show_current = true;
2940 civilize_flag = true;
2941 show_numeric = true;
2942 show_missing = true;
2943 current_flag = true;
2944 current_tfm = true; /* search for TFMs in current dir as well */
2945 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2946 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2947 file_method = true; /* use file_p (_findfirst) not readable (access) */
2948 /* waitflush = true; */ /* flushed 97/Dec/24 */
2949 c_style_flag = false; /* use c-style error output */
2950 show_fmt_flag = true; /* show format file in log */
2951 show_tfm_flag = false; /* don't show metric file in log */
2952 shorten_file_name = false; /* don't shorten file names to 8+3 */
2953 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2954 truncate_long_lines = true; /* truncate long lines */
2955 tab_step = 0; /* do not replace tabs with spaces */
2956 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2957 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2958 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2959 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2960 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2961 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2962 knuth_flag = false; /* allow extensions to TeX */
2963 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2964 full_file_name_flag = true; /* new default 2000 June 18 */
2965 save_strings_flag = true; // 2000 Aug 15
2966 errout = stdout; /* as opposed to stderr say --- used ??? */
2967 abort_flag = 0; // not yet hooked up ???
2968 err_level = 0; // not yet hooked up ???
2969 new_hyphen_prime = 0;
2970 #ifdef VARIABLETRIESIZE
2971 /* trie_size = default_trie_size; */
2977 #ifdef ALLOCATEDVIBUF
2980 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2981 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2982 share_flag = 0; /* revert to fopen for now */
2984 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2985 programpath = xstrdup(av[0]); /* extract path executable */
2986 strip_name(programpath); /* strip off yandytex.exe */
2988 //format_name = "yandytex";
2989 format_name = "plain"; /* format name if specified on command line */
2993 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
2994 return -1; // in case of error
2996 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
2997 return -1; // in case of error
2999 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
3001 /* Print version *after* banner ? */ /* does this get in log file ? */
3003 // showversion (stdout);
3004 // showversion (log_line);
3006 strcat(log_line, "\n");
3007 show_line(log_line, 0);
3008 stampcopy(log_line);
3009 strcat(log_line, "\n");
3010 show_line(log_line, 0);
3012 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
3014 /* if we aren't including current directory in any directory lists */
3015 /* then makes no sense to avoid them separately for TFM files ... */
3016 /* (that is, the ./ is already omitted from the dir list in that case */
3017 if (!current_flag && !current_tfm)
3018 current_tfm = true; /* 94/Jan/24 */
3019 return 0; // success
3022 /* E sets environment variable ? */
3024 void initial_memory (void)
3026 /* set initial memory allocations */
3027 if (mem_extra_high < 0) mem_extra_high = 0;
3028 if (mem_extra_low < 0) mem_extra_low = 0;
3029 if (mem_initex < 0) mem_initex = 0;
3031 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3032 if (mem_extra_high != 0 || mem_extra_low != 0) {
3033 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3034 mem_extra_high = 0; mem_extra_low = 0;
3038 if (mem_initex != 0) {
3039 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3042 if (trie_size != 0) {
3043 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3044 /* trie_size = 0; */
3047 if (mem_initex == 0) mem_initex = default_mem_top;
3048 if (trie_size == 0) trie_size = default_trie_size;
3049 /* Just in case user mistakenly specified words instead of kilo words */
3050 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3051 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3052 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3053 #ifdef ALLOCATEHIGH /* not used anymore */
3054 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3055 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3056 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3059 #ifdef ALLOCATELOW /* not used anymore */
3060 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3061 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3062 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3065 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3066 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3067 /* mem_initex = 2048 * 1024; */
3069 #ifdef ALLOCATEDVIBUF
3070 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3071 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3072 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3073 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3074 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3076 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3077 if (new_hyphen_prime > 0) {
3079 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3081 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3082 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3084 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3085 show_line(log_line, 0);
3089 if (percent_grow > 100) percent_grow = percent_grow - 100;
3090 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3091 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3094 /**********************************************************************/
3096 void perrormod (char *s)
3098 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3099 show_line(log_line, 1);
3105 fflush(stdout); /* ??? */
3106 fflush(stderr); /* ??? */
3107 (void) _getch(); /* ??? */
3111 void checkpause (int flag)
3114 int debug_pause = 0;
3115 /* don't stop if in Q (quiet) or R (run) mode */
3116 /* stop only in S (scroll) and T (TeX) mode */
3117 if (interaction >= 0 && interaction < 2) flag = 0; /* 98/Jun/30 */
3118 s = grabenv("DEBUGPAUSE");
3119 if (s != NULL) sscanf(s, "%d", &debug_pause);
3120 if (flag < 0) return;
3122 if (debug_pause || flag > 0) {
3125 show_line("Press any key to continue . . .\n", 0);
3132 void check_enter (int argc, char *argv[])
3135 char current[FILENAME_MAX];
3136 if (grabenv("DEBUGPAUSE") != NULL) {
3137 (void) _getcwd(current, sizeof(current));
3138 sprintf(log_line, "Current directory: `%s'\n", current);
3139 show_line(log_line, 0);
3140 for (m = 0; m < argc; m++) {
3141 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3142 show_line(log_line, 0);
3149 void checkexit (int n) { /* 95/Oct/28 */
3155 /*************************************************************************/
3157 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3158 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3159 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3160 /* this is then undone in tex3.c both for fopen input and output */
3161 /* not ideal, since pseudo name appears in log and in error messages ... */
3163 void hidetwiddle (char *name)
3168 sprintf(log_line, "Hidetwiddle %s", name);
3169 show_line(log_line, 0);
3172 /* while (*s != '\0' && *s != ' ') { */
3173 while (*s != '\0') {
3174 if (*s == '~' && pseudo_tilde != 0)
3175 *s = (char) pseudo_tilde; /* typically 254 */
3176 else if (*s == ' ' && pseudo_space != 0)
3177 *s = (char) pseudo_space; /* typically 255 */
3182 sprintf(log_line, "=> %s\n", name);
3183 show_line(log_line, 0);
3188 void deslash_all (int ac, char **av)
3190 char buffer[PATH_MAX];
3193 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3194 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3196 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3198 check_enter(ac, av); /* 95/Oct/28 */
3200 /* environment variables for output directories (as in PC TeX) */
3202 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3203 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3204 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3206 strcpy(buffer, av[0]); /* get path to executable */
3207 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3208 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3209 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3210 s = buffer + strlen(buffer) - 1;
3211 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3212 texpath = xstrdup(buffer);
3214 /* Hmm, we may be operating on DOS environment variables here !!! */
3216 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3217 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3218 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3221 unixify (texpath); /* 94/Jan/25 */
3222 /* if output directories given, deslashify them also 1993/Dec/12 */
3223 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3224 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3225 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3228 /* deslash TeX source file (and format, if format specified) */
3229 /* and check args to see whether format was specified */
3231 /* NOTE: assuming that command line arguments are in writable memory ! */
3232 /* if (trace_flag || debug_flag)
3233 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3234 /* if (optind < ac) { */ /* bkph */
3235 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3237 if (trace_flag || debug_flag) {
3238 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3239 optind, av[optind], ac);
3240 show_line(log_line, 0);
3242 unixify(av[optind]);
3244 if (pseudo_tilde != 0 || pseudo_space != 0)
3245 hidetwiddle (av[optind]); /* 95/Sep/25 */
3246 /* For Windows NT, lets allow + instead of & for format specification */
3247 if (*av[optind] == '&' || *av[optind] == '+') {
3248 format_spec = 1; /* format file specified */
3249 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3250 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3251 if (optind + 1 < ac) {
3253 if (trace_flag || debug_flag) {
3254 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3255 optind+1, av[optind+1], ac);
3256 show_line(log_line, 0);
3258 unixify(av[optind+1]);
3260 if (pseudo_tilde != 0 || pseudo_space != 0)
3261 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3267 /* The above seems to assume that arguments that don't start with '-' */
3268 /* are file names or format names - what if type in control sequences? */
3270 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3272 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3273 /* interaction == 1 => nonstop mode (omit all stops) */
3274 /* interaction == 2 => scroll mode (omit error stops) */
3275 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3277 /* main entry point follows */
3279 /* this gets called pretty much right away in `main' in texmf.c */
3281 /* note: those optarg == 0 test don't really work ... */
3282 /* note: optarg starts at = in case of x=... */
3284 int init (int ac, char **av)
3286 char initbuffer[PATH_MAX];
3289 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3296 show_line("TEXDEBUG\n", 0);
3297 trace_flag = 1; /* 94/April/14 */
3300 if (sizeof(memory_word) != 8) { /* compile time test */
3301 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3302 show_line(log_line, 1);
3305 start_time = clock(); /* get time */
3306 main_time = start_time; /* fill in, in case file never opened */
3308 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3310 /* reset all allocatable memory pointers to NULL - in case we drop out */
3315 #ifdef ALLOCATEZEQTB
3321 #ifdef ALLOCATESAVESTACK
3324 #ifdef ALLOCATEDVIBUF
3327 #ifdef ALLOCATEBUFFER
3328 buffer = NULL; /* new 1999/Jan/7 need to do early */
3329 current_buf_size = 0;
3330 buffer = realloc_buffer (initial_buf_size);
3331 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3333 hyph_list = NULL; hyph_word = NULL;
3334 trie_taken = NULL; trie_hash = NULL;
3343 log_opened = false; /* so can tell whether opened */
3344 interaction = -1; /* default state => 3 */
3345 missing_characters = 0; /* none yet! */
3346 workingdirectory = false; /* set from dviwindo.ini & command line */
3347 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3348 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3349 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3350 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3351 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3353 if (reorder_arg_flag) reorderargs(ac, av);
3355 if (init_commands(ac, av))
3356 return -1; // failure
3358 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3360 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3361 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3362 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3363 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3364 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3366 first_pass_count = 0;
3367 second_pass_count = 0;
3368 final_pass_count = 0;
3369 paragraph_failed = 0;
3376 closed_already=0; // so can only do once
3378 if (trace_flag) show_line("Entering init (local)\n", 0);
3380 /* Print version *after* banner ? */ /* does this get in log file ? */
3382 probe_memory(); /* show top address */
3383 ini_max_address = max_address; /* initial max address */
3384 if (trace_flag) show_maximums(stdout);
3386 if (heap_flag) (void) heap_dump(stdout, 1);
3391 deslash_all(ac, av); /* deslash and note if format specified */
3393 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3397 if (format_spec && mem_spec_flag) {
3398 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3401 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3402 return -1; // if failed to allocate
3404 /* following is more or less useless since most all things not yet alloc */
3405 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3407 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3411 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3414 if (trace_flag) show_line("Leaving init (local)\n", 0);
3415 return 0; // success
3418 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3420 /* void show_inter_val (clock_t start, clock_t end) { */
3421 void show_inter_val (clock_t interval)
3423 /* clock_t interval; */
3424 /* int seconds, tenths; */
3425 /* int seconds, tenths, hundredth; */
3426 int seconds, tenths, hundredth, thousands;
3427 /* interval = end - start; */
3428 /* sanity check whether positive ? */
3429 if (interval >= CLK_TCK * 10) {
3430 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3431 seconds = tenths / 10;
3432 tenths = tenths % 10;
3433 sprintf(log_line, "%d.%d", seconds, tenths);
3434 show_line(log_line, 0);
3436 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3437 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3438 seconds = hundredth / 100;
3439 hundredth = hundredth % 100;
3440 sprintf(log_line, "%d.%02d", seconds, hundredth);
3441 show_line(log_line, 0);
3443 else if (interval > 0) { /* 94/Oct/4 */
3444 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3445 seconds = thousands / 1000;
3446 thousands = thousands % 1000;
3447 sprintf(log_line, "%d.%03d", seconds, thousands);
3448 show_line(log_line, 0);
3450 else show_line("0", 0); /* 95/Mar/1 */
3453 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3454 /* shows various times, warning about missing chars */
3456 int endit (int flag)
3459 finish_time = clock();
3460 if (missing_characters != 0) flag = 1;
3461 if (missing_characters) {
3463 "! There %s %d missing character%s --- see log file\n",
3464 (missing_characters == 1) ? "was" : "were", missing_characters,
3465 (missing_characters == 1) ? "" : "s");
3466 show_line(log_line, 0);
3468 if (free_memory() != 0) flag++;
3470 /* show per page time also ? */
3472 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3473 start_time, main_time, finish_time); */
3474 show_line("Total ", 0);
3475 /* show_inter_val(start_time, finish_time); */
3476 show_inter_val(finish_time - start_time);
3477 show_line(" sec (", 0);
3478 /* show_inter_val(start_time, main_time); */
3479 show_inter_val(main_time - start_time);
3480 show_line(" format load + ", 0);
3481 /* show_inter_val(main_time, finish_time); */
3482 show_inter_val(finish_time - main_time);
3483 show_line(" processing) ", 0);
3484 if (total_pages > 0) {
3485 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3486 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3487 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3488 show_inter_val ((finish_time - main_time) / total_pages);
3489 show_line(" sec per page", 0);
3499 /********************************************************************************/
3501 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3505 #define MAXCOLUMN 78
3507 void print_cs_name (FILE *output, int h)
3512 textof = hash[h].v.RH;
3513 if (textof == 0) return; /* ignore if text() == 0 */
3515 if (textcolumn != 0) {
3516 sprintf(log_line, ", ");
3517 if (output != NULL) fprintf(output, log_line);
3518 else show_line(log_line, 0);
3521 if (textcolumn + n + 2 >= MAXCOLUMN) {
3522 sprintf(log_line, "\n");
3523 if (output == stderr) show_line(log_line, 1);
3524 else if (output == stdout) show_line(log_line, 0);
3525 else fputs(log_line, output);
3529 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3532 if (output == stderr) show_line(log_line, 1);
3533 else if (output == stdout) show_line(log_line, 0);
3534 else fprintf(output, log_line);
3538 int compare_strn (int, int, int, int); /* in tex9.c */
3540 /* compare two csnames in qsort */
3542 int compare_cs (const void *cp1, const void *cp2)
3544 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3547 textof1 = hash[c1].v.RH;
3548 textof2 = hash[c2].v.RH;
3549 l1 = length(textof1);
3550 l2 = length(textof2);
3551 k1 = str_start[textof1];
3552 k2 = str_start[textof2];
3553 /* showstring (k1, l1); */
3554 /* showstring (k2, l2); */
3555 return compare_strn (k1, l1, k2, l2);
3560 /* Allocate table of indeces to allow sorting on csname */
3561 /* Allocate flags to remember which ones already listed at start */
3563 void print_cs_names (FILE *output, int pass)
3565 int h, k, ccount, repeatflag;
3567 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3569 if (pass == 0 && csused == NULL) {
3570 csused = (char *) malloc (nfcs);
3571 if (csused == NULL) return;
3573 memset(csused, 0, nfcs);
3575 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3580 for (h = hash_base + 1; h < nfcs; h++) {
3581 if (pass == 1 && csused[h]) continue;
3582 if (hash[h].v.RH != 0) {
3583 if (pass == 0) csused[h] = 1;
3588 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3589 ccount, (pass == 1) ? "new" : "");
3590 if (output == stderr) show_line(log_line, 1);
3591 else if (output == stdout) show_line(log_line, 0);
3592 else fprintf(output, log_line);
3594 if (ccount > 0) { /* don't bother to get into trouble */
3596 cnumtable = (int *) malloc (ccount * sizeof(int));
3597 if (cnumtable == NULL) return;
3600 /* for (h = 515; h < (hash_size + 780); h++) { */
3601 for (h = hash_base+1; h < nfcs; h++) {
3602 if (pass == 1 && csused[ h]) continue;
3603 if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3606 qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3609 for (k = 0; k < ccount; k++) {
3611 if (pass == 1 && csused[ h]) continue;
3612 print_cs_name(output, h);
3614 sprintf(log_line, "\n");
3615 if (output == stderr) show_line(log_line, 1);
3616 else if (output == stdout) show_line(log_line, 0);
3617 else fprintf(output, log_line);
3618 free((void *)cnumtable);
3621 if (pass == 1 && csused != NULL) {
3627 /***************** font info listing moved from TEX9.C ******************/
3629 void showstring (int k, int l)
3632 while (l-- > 0) *s++ = str_pool[k++];
3635 show_line(log_line, 0);
3638 /* compare two strings in str_pool (not null terminated) */
3639 /* k1 and k2 are positions in string pool */
3640 /* l1 and l2 are lengths of strings */
3642 int compare_strn (int k1, int l1, int k2, int l2)
3645 /* while (l1-- > 0 && l2-- > 0) { */
3646 while (l1 > 0 && l2 > 0) {
3649 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3650 if (c1 > c2) return 1;
3651 else if (c2 > c1) return -1;
3655 if (l1 > 0) return 1; /* first string longer */
3656 else if (l2 > 0) return -1; /* second string longer */
3657 return 0; /* strings match */
3660 /* compare two font names and their at sizes in qsort */
3662 int compare_fnt (const void *fp1, const void *fp2)
3664 int f1, f2, l1, l2, k1, k2, s;
3667 l1 = length(font_name[f1]);
3668 l2 = length(font_name[f2]);
3669 k1 = str_start[font_name[f1]];
3670 k2 = str_start[font_name[f2]];
3671 /* showstring (k1, l1); */
3672 /* showstring (k2, l2); */
3673 s = compare_strn (k1, l1, k2, l2);
3674 /* sprintf(log_line, "%d\n", s); */
3675 if (s != 0) return s;
3676 if (font_size[f1]> font_size[f2]) return 1;
3677 else if (font_size[f1]< font_size[f2]) return -1;
3678 return 0; /* should not ever get here */
3681 /* compare two font names */
3683 int compare_fnt_name (int f1, int f2)
3685 int l1, l2, k1, k2, s;
3686 l1 = length(font_name[f1]);
3687 l2 = length(font_name[f2]);
3688 k1 = str_start[font_name[f1]];
3689 k2 = str_start[font_name[f2]];
3690 /* showstring (k1, l1); */
3691 /* showstring (k2, l2); */
3692 s = compare_strn (k1, l1, k2, l2);
3693 /* sprintf(log_line, "%d\n", s); */
3697 /* decode checksum information */
3699 unsigned long checkdefault = 0x59265920; /* default signature */
3701 int decode_fourty (unsigned long checksum, char *codingvector)
3705 /* char codingvector[6+1]; */
3707 /* if (checksum == checkdefault) { */
3708 if (checksum == 0) {
3709 /* strcpy(codingvector, "unknown"); */
3710 strcpy(codingvector, "unknwn");
3713 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3714 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3715 strcpy (codingvector, "fixed "); /* if not specified ... */
3716 return 1; /* no info available */
3719 for (k = 0; k < 6; k++) {
3720 c = (int) (checksum % 40);
3721 checksum = checksum / 40;
3722 if (c <= 'z' - 'a')c = c + 'a';
3723 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3724 else if (c == 36) c = '-';
3725 else if (c == 37) c = '&';
3726 else if (c == 38) c = '_';
3727 else c = '.'; /* unknown */
3728 codingvector[5-k] = (char) c;
3730 codingvector[6] = '\0';
3732 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3733 return 0; /* encoding info returned in codingvector */
3736 double sclpnt (long x)
3739 pt = (double) x / 65536.0;
3740 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3744 // Shows list of fonts in log file
3746 void dvi_font_show(internal_font_number f, int suppressname)
3748 int a, l, k, n, for_end;
3749 unsigned long checksum;
3750 char checksumvector[8];
3753 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3754 /* fprintf (log_file, "%d ", suppressname); */
3755 /* suppressname = 0; */
3756 putc(' ', log_file);
3757 if (suppressname == 0) {
3758 a = length(font_area[f]);
3759 l = length(font_name[f]);
3760 k = str_start[font_area[f]];
3761 for_end = str_start[font_area[f]+ 1]- 1;
3762 if (k <= for_end) do {
3763 putc(str_pool[k], log_file);
3764 } while(k++ < for_end, stdout);
3765 k = str_start[font_name[f]];
3766 for_end = str_start[font_name[f]+ 1]- 1;
3767 if (k <= for_end) do {
3768 putc(str_pool[k], log_file);
3769 } while(k++ < for_end);
3772 for (k = a+l; k < 16; k++) putc(' ', log_file);
3773 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3774 fputs(buffer, log_file);
3775 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3776 if (suppressname == 0) {
3778 // n = strlen(log_file);
3779 for (k = n; k < 16; k++) putc(' ', log_file);
3780 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3781 font_check[f].b2) << 8 | font_check[f].b3;
3782 decode_fourty(checksum, checksumvector);
3783 fprintf(log_file, "encoding: %s..", checksumvector);
3785 putc('\n', log_file);
3788 /* Allocate table of indeces to allow sorting on font name */
3790 void show_font_info (void)
3792 int k, m, fcount, repeatflag;
3796 for (k = 1; k <= font_ptr; k++)
3797 if (font_used[k])fcount++;
3799 if (fcount == 0) return; /* don't bother to get into trouble */
3801 fnumtable = (short *) malloc (fcount * sizeof(short));
3803 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3805 fprintf(log_file, "\nUsed %d font%s:\n",
3806 fcount, (fcount == 1) ? "" : "s");
3809 for (k = 1; k <= font_ptr; k++)
3810 if (font_used[k])fnumtable[fcount++] = (short) k;
3812 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3815 for (m = 0; m < fcount; m++) {
3817 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3819 else repeatflag = 0;
3821 dvi_font_show(fnumtable[ m], repeatflag);
3824 free((void *)fnumtable);
3827 ////////////////////////////////////////////////////////////////////////////
3829 // Here follows the new stuff for the DLL version
3835 #define SHOWLINEBUFLEN 256
3837 char showlinebuf[SHOWLINEBUFLEN];
3839 // char log_line[MAXLINE];
3841 #define WHITESPACE " \t\n\r"
3843 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3845 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3847 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3848 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3849 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3851 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3853 void ClearShowBuffer (void)
3855 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3856 if (hConsoleWnd != NULL)
3857 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3861 // communicate with DVIWindo (for yandytex.dll)
3863 void show_line (char *line, int errflag) { /* 99/June/11 */
3866 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3867 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3868 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3870 // abort_flag++; // kill job in this case ???
3874 if (showlineinx > 0) ClearShowBuffer();
3876 if (hConsoleWnd != NULL)
3877 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3881 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3882 if (ret == IDCANCEL) {
3884 uexit(1); // dangerous reentry possibility ?
3889 // Provide means for buffering up individual characters
3891 void show_char (int chr) {
3892 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3893 showlinebuf[showlineinx++] = (char) chr;
3894 if (chr == '\n') ClearShowBuffer();
3897 void winshow(char *line) {
3898 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3901 void winerror (char *line) {
3903 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3904 if (ret == IDCANCEL) abort_flag++;
3907 // argument info constructed from command line
3913 // need to be careful here because of quoted args with spaces in them
3914 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3916 int makecommandargs (char *line)
3920 unsigned char *s, *t; // fix 2000 June 18
3922 if (line == NULL) return -1; /* sanity check */
3924 // winerror(line); // debugging only
3926 // s = strtok(line, WHITESPACE);
3927 // while (s != NULL) { /* count arguments */
3929 // s = strtok(NULL, WHITESPACE);
3934 while (*s != '\0') {
3935 while (*s <= 32 && *s > 0) s++;
3936 if (*s == '\0') break;
3938 while (*t > 32 && *t != '\"') t++;
3941 while (*t > 0 && *t != '\"') t++;
3942 if (*t == '\0') break;
3945 // xargv[xargc] = s;
3947 if (*t == '\0') break;
3952 if (xargc == 0) return -1; /* nothing to do */
3954 xargv = (char **) malloc(xargc * sizeof(char *));
3955 if (xargv == NULL) {
3956 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3963 while (*s != '\0') {
3964 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3965 if (*s == '\0') break;
3967 while (*t > ' ' && *t != '\"') t++;
3970 while (*t > 0 && *t != '\"') t++;
3971 if (*t == '\0') break;
3974 // winerror(s); // debugging only
3977 if (*t == '\0') break;
3983 // for (k = 0; k < xargc; k++) { /* create pointers to args */
3984 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
3986 // s += strlen(s) +1;
3992 for (k = 0; k < xargc; k++) {
3993 sprintf(s, "%d\t%s\n", k, xargv[k]);
4001 // refers to TeXAsk in dviwindo.c
4003 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4004 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
4006 // called from tex0.c only --- by initterm and term_input
4008 //int ConsoleInput (char *question, char *buffer)
4009 int ConsoleInput (char *question, char *help, char *buffer)
4013 if (AskUserCall == NULL) return 0;
4014 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4015 // show_line(log_line, 1);
4018 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
4019 // strcpy(buffer, "x");
4020 // strcat(buffer, " "); // ???
4021 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4022 // show_line(log_line, 1);
4023 // input_line_finish(); // ???
4024 // s = buffer + strlen(buffer);
4025 // *s++ = ' '; // space terminate
4026 // *s++ = '\0'; // and null terminate
4027 // returning != 0 means EOF or ^Z
4031 // This is the new entry point of DLL called from DVIWindo
4032 // ARGS: console window to send messages to, command line, callback fun
4033 // no console window output if hConsole is NULL
4034 // returns -1 if it fails --- returns 0 if it succeeds
4036 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4037 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4041 abort_flag = 0; // redundant
4042 hConsoleWnd = NULL; // redundant
4044 AskUserCall = AskUser; // remember callback
4046 hConsoleWnd = hConsole; // remember console window handle
4048 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4049 // if (grabenv("DEBUGPAUSE") != NULL) {
4050 // show_line(line, 0); // debugging - show command line
4051 // show_line("\n", 0);
4054 xargc = makecommandargs(line); // sets up global *xargv[]
4056 if (xargc < 0) return -1; // sanity check
4058 if (hConsoleWnd != NULL)
4059 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4060 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4063 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
4065 if (err_level > 0 || abort_flag > 0) {
4066 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4067 // err_level, abort_flag);
4068 // winerror(log_line);
4071 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
4072 // if (psbufpos > 0) PSputs("", output); // output already closed
4074 if (hConsoleWnd != NULL) {
4075 if (err_level > 0 || abort_flag > 0) flag = 1;
4076 else flag = 0; // pass along error indication
4077 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
4079 // PScallback = NULL;
4082 if (xargv != NULL) free(xargv);
4083 if (abort_flag) return -1;
4087 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4090 switch (fdwReason) {
4091 case DLL_PROCESS_ATTACH:
4092 // The DLL is being mapped into the process's address space
4093 // place to allocate memory ???
4094 // return FALSE if this fails
4095 hInstanceDLL = hInstDll; /* remember it */
4098 case DLL_THREAD_ATTACH:
4099 // A thread is being created
4102 case DLL_THREAD_DETACH:
4103 // A thread is exiting cleanly
4106 case DLL_PROCESS_DETACH:
4107 // The DLL is being unmapped from the process's address space
4108 // place to free any memory allocated
4109 // but make sure it in fact *was* allocated
4110 hInstanceDLL = NULL; /* forget it */
4113 return(TRUE); // used only for DLL_PROCESS_ATTACH
4115 #endif // end of new stuff for DLL version
4117 //////////////////////////////////////////////////////////////////////////////
4121 /* NOTE: current_tfm = false (-c)
4122 not checking for TFM in current directory saves 0.1 sec
4123 (0.2 if file_method = false (-G) */
4125 /* NOTE: test_dir_access = false (-b):
4126 not checking whether readable file is a directory saves maybe 0.5 sec
4127 BUT only if file_method = false (-G) - otherwise its irrelevant */
4129 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4130 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4131 BUT not if current_tfm = false (-c) */
4133 /* NOTE: file_method = false (-G) --- method for checking file accessible
4134 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4136 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4138 /* constants for _heapchk/_heapset/_heapwalk routines */
4139 /* #define _HEAPEMPTY (-1) */
4140 /* #define _HEAPOK (-2) */
4141 /* #define _HEAPBADBEGIN (-3) */
4142 /* #define _HEAPBADNODE (-4) */
4143 /* #define _HEAPEND (-5) */
4144 /* #define _HEAPBADPTR (-6) */
4146 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4148 /* buffercopy no longer used */
4150 /* To Knuthian reset right when command line interpreted */