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[] =
526 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
530 /* Attempt to get at problem with eqtb ... temporarily abandoned */
532 void check_eqtb (char *act)
535 memory_word *eqtb = zeqtb;
536 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
537 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
538 if (eqtb[k].cint != 0) {
541 show_line("EQTB ", 0);
543 sprintf(log_line, "%d ", k);
544 show_line(log_line, 0);
545 if (count++ > 256) break;
548 if (count != 0) show_char('\n');
552 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
556 /* ad hoc default minimum growth in memory realloc is 62% */
557 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
558 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
559 int total_allocated = 0; /* total memory allocated so far */
560 int ini_max_address = 0; /* maximum address when starting */
561 int max_address = 0; /* maximum address seen in allocated memory */
565 // DON'T USE THIS in DLL VERSION
569 unsigned int heapthreshold=0; /* smallest size block interested in ... */
571 unsigned int heap_dump (FILE *output, int verbose)
573 unsigned int total=0;
574 struct _heapinfo hinfo;
579 if (verbose) fprintf(output, "HEAP DUMP:\n");
581 /* if ((n = _heapchk ()) != _HEAPOK) { */
588 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
590 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
593 hinfo._pentry = NULL;
594 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
595 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
596 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
598 end_block = (int) hinfo._pentry + hinfo._size;
599 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
600 if (hinfo._size >= heapthreshold && verbose)
601 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
602 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
603 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
606 switch (heapstatus) {
608 if (verbose) fprintf(output, "OK - empty heap\n");
611 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
614 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
617 fprintf(output, "ERROR - %s\n", "bad start of heap");
620 fprintf(output, "ERROR - %s\n", "bad node in heap");
628 void show_maximums (FILE *output)
631 unsigned heaptotal=0; /* no longer used */
632 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
634 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
635 // if (output != NULL) fputs(log_line, output); // log file
636 // else if (flag == 0) show_line(log_line, 0); // informative
637 // else if (flag == 1) show_line(log_line, 1); // error
638 if (output == stderr) show_line(log_line, 1);
639 else if (output == stdout) show_line(log_line, 0);
640 else fputs(log_line, output);
643 /* our own version of realloc --- avoid supposed MicroSoft version bug */
644 /* also tries _expand first, which can avoid address growth ... */
647 void *ourrealloc (void *old, size_t new_size)
650 size_t old_size, overlap;
652 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
653 if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
655 if (old == NULL) return malloc (new_size); /* no old block - use malloc */
657 old_size = _msize (old);
658 if (old_size >= new_size && old_size < new_size + 4) return old;
659 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
662 show_line("BEFORE REALLOC: \n", 0);
664 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
668 mnew = _expand (old, new_size); /* first try and expand in place */
671 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
672 mnew, new_size, old, old_size);
673 show_line(log_line, 0);
677 /* *********************************************************************** */
678 /* do this if you want to call the real realloc next - */
679 mnew = realloc (old, new_size);
682 show_line("AFTER REALLOC: \n", 0);
684 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
688 if (mnew != NULL) return mnew;
689 /* we are screwed typically if we ever drop through here - no more space */
690 /* *********************************************************************** */
691 mnew = malloc (new_size); /* otherwise find new space */
692 if (mnew == NULL) return mnew; /* if unable to allocate */
693 if (old_size < new_size) overlap = old_size;
694 else overlap = new_size;
695 memcpy (mnew, old, overlap); /* copy old data to new area */
696 free(old); /* free the old area */
701 void memory_error (char *s, int n)
704 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
705 show_maximums(log_file);
707 if (heap_flag) (void) heap_dump(log_file, 1);
710 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
711 show_line(log_line, 1);
712 show_maximums(stderr);
714 if (heap_flag) (void) heap_dump(stderr, 1);
716 /* exit (1); */ /* 94/Jan/22 */
717 /* return to let TeX do its thing (such as complain about runaway) */
718 /* don't set abort_flag here */
721 void trace_memory (char *s, int n)
723 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
724 show_line(log_line, 0);
727 void update_statistics (int address, int size, int oldsize)
729 if (address + size > max_address) max_address = address + size;
730 total_allocated = total_allocated + size - oldsize;
733 void probe_memory (void)
736 s = (char *) malloc (4); /* get current top address */
738 update_statistics ((int) s, 0, 0); /* show where we are */
741 void probe_show (void)
744 show_maximums(stdout);
746 if (heap_flag) (void) heap_dump(stdout, 1);
750 size_t roundup (size_t n)
752 if ((n % 4) == 0) return n;
753 else return ((n / 4) + 1) * 4;
757 /* using allocating hyphenation trie slows things down maybe 1% */
758 /* but saves typically (270k - 55k) = 215k of memory */
759 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
760 /* since hyphenation trie cannot be extended (after iniTeX) */
761 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
763 /* NOTE: we don't ever reallocate these */
764 /* returns -1 if it fails */
766 int allocate_tries (int trie_max)
769 /* if (trie_max > trie_size) {
770 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
771 trie_max, trie_size);
772 show_line(log_line, 1);
774 } */ /* ??? removed 1993/dec/17 */
775 if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
776 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
777 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
778 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
779 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
781 if (trace_flag) trace_memory("hyphen trie", n);
782 trie_trl = (halfword *) malloc (roundup(nl));
783 trie_tro = (halfword *) malloc (roundup(no));
784 trie_trc = (quarterword *) malloc (roundup(nc));
785 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL) {
786 memory_error("hyphen trie", n);
790 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
791 show_line(log_line, 0);
793 update_statistics ((int) trie_trl, nl, 0);
794 update_statistics ((int) trie_tro, no, 0);
795 update_statistics ((int) trie_trc, nc, 0);
796 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
797 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
799 probe_show(); /* 94/Mar/25 */
804 #ifdef ALLOCATEHYPHEN
805 bool prime (int); /* test function later in this file */
807 int current_prime = 0; /* remember in case reallocated later */
809 /* we don't return an address here, since TWO memory regions allocated */
810 /* plus, we don't really reallocate, we FLUSH the old information totally */
811 /* returns -1 if it fails */
813 int realloc_hyphen (int hyphen_prime)
817 if (!prime(hyphen_prime))
819 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
820 show_line(log_line, 1);
824 /* need not/cannot preserve old contents when hyphen prime is changed */
825 /* if (hyph_list != NULL) free(hyph_list); */
826 /* if (hyph_word != NULL) free(hyph_word); */
827 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
828 nw = (hyphen_prime + 1) * sizeof(str_number);
829 nl = (hyphen_prime + 1) * sizeof(halfword);
831 if (trace_flag) trace_memory("hyphen exception", n);
832 /* initially hyph_word will be NULL so this acts like malloc */
833 /* hyph_word = (str_number *) malloc (nw); */
834 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
835 /* initially hyph_list will be NULL so this acts like malloc */
836 /* hyph_list = (halfword *) malloc (nl); */
837 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
838 if (hyph_word == NULL || hyph_list == NULL) {
839 memory_error("hyphen exception", n);
843 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
844 show_line(log_line, 0);
846 /* cannot preserve old contents when hyphen prime is changed */
848 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
850 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
853 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
855 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
857 hyph_count = 0; /* or use reset_hyphen() in itex.c */
858 if (current_prime != 0) {
859 update_statistics ((int) hyph_word, nw,
860 (current_prime + 1) * sizeof(str_number));
861 update_statistics ((int) hyph_list, nl,
862 (current_prime + 1) * sizeof(halfword));
865 update_statistics ((int) hyph_word, nw, 0);
866 update_statistics ((int) hyph_list, nl, 0);
868 current_prime = hyphen_prime;
869 if (trace_flag) probe_show(); /* 94/Mar/25 */
874 int current_mem_size=0; /* current total words in main mem allocated -1 */
876 /* this gets called from itex.c when it figures out what mem_top is */
877 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
878 /* initial allocation only, may get expanded later */
879 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
880 /* returns NULL if it fails */
883 /* initial main memory alloc - mem_top */
884 memory_word *allocate_main_memory (int size)
888 /* Using -i *and* pre-loading format */ /* in this case get called twice */
889 /* Get rid of initial blank memory again or use realloc ... */
890 /* Could we avoid this by detecting presence of & before allocating ? */
891 /* Also, if its already large enough, maybe we can avoid this ? */
892 /* don't bother if current_mem_size == mem_max - mem_start ? */
893 if (mainmemory != NULL) {
894 /* free(mainmemory); */
895 /* mainmemory = NULL; */
896 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
897 /* if (mem_spec_flag)
898 show_line("Cannot change initial main memory size when format is read\n", 1);*/
901 mem_top = mem_bot + size;
902 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
903 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
906 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
907 if (mem_extra_low != 0 && !is_initex)
908 mem_start = mem_bot - mem_extra_low; /* increase main memory */
910 mem_start = 0; /* bottom of memory allocated by system */
911 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
912 mem_min = 0; /* bottom of area made available to TeX */
913 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
914 if (trace_flag) trace_memory("main memory", n);
915 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
916 /* normally mainmemory == NULL here so acts like malloc ... */
917 mainmemory = (memory_word *) REALLOC (mainmemory, n);
918 if (mainmemory == NULL) {
919 memory_error("initial main memory", n);
920 // exit (1); /* serious error */
924 sprintf(log_line, "Address main memory == %d\n", mainmemory);
925 show_line(log_line, 0);
928 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
930 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
931 show_line(log_line, 0);
933 update_statistics ((int) mainmemory, n,
934 (current_mem_size + 1) * sizeof (memory_word));
935 /* current_mem_size = (mem_max - mem_start + 1); */
936 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
937 if (trace_flag) probe_show(); /* 94/Mar/25 */
938 return zzzaa; /* same as zmem, mem 94/Jan/24 */
940 #endif /* end of ALLOCATEMAIN */
943 /* int firstallocation = 1; */
945 /* increase main memory allocation at low end and high end */
946 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
947 /* returns NULL if it fails */
949 memory_word *realloc_main (int losize, int hisize)
952 int newsize = 0; /* to quieten compiler */
953 int n = 0; /* to quieten compiler */
954 memory_word * newmemory = NULL; /* to quieten compiler */
956 /* if (losize == 0 && hisize > 0) runawayflag = 1;
957 else runawayflag = 0; */ /* 94/Jan/22 */
960 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
961 show_line(log_line, 0);
964 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
966 show_line("Please use `-m=...' on command line\n", 0);
967 // abort_flag++; // ???
971 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
972 show_line(log_line, 0);
974 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
975 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
976 // abort_flag++; // ???
979 /* first allocation should expand *both* lo and hi */
980 if (hisize == 0 && mem_end == mem_max) hisize = losize;
981 if (losize == 0 && mem_start == mem_min) losize = hisize;
982 /* try and prevent excessive frequent reallocations */
983 /* while avoiding over allocation by too much */
984 minsize = current_mem_size / 100 * percent_grow;
985 if (losize + hisize < minsize) {
986 if (losize > 0 && hisize > 0) {
987 losize = minsize / 2;
988 hisize = minsize / 2;
990 else if (losize > 0) losize = minsize;
991 else if (hisize > 0) hisize = minsize;
993 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
994 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
996 for (k = 0; k < MAXSPLITS; k++) {
997 newsize = current_mem_size + losize + hisize;
998 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
999 while (newsize >= max_mem_size) {
1000 losize = losize / 2; hisize = hisize / 2;
1001 newsize = current_mem_size + losize + hisize;
1004 n = (newsize + 1) * sizeof (memory_word);
1005 if (trace_flag) trace_memory("main memory", n);
1006 newmemory = (memory_word *) REALLOC (mainmemory, n);
1007 if (newmemory != NULL) break; /* did we get it ? */
1008 if (current_mem_size == 0) break; /* in case we ever use for initial */
1009 losize = losize / 2; hisize = hisize / 2;
1012 if (newmemory == NULL) {
1013 memory_error("main memory", n);
1014 return zzzaa; /* try and continue with TeX !!! */
1017 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1018 show_line(log_line, 0);
1021 /* shift everything upward to make space for new low area */
1023 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1024 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1025 show_line(log_line, 0);
1027 memmove (newmemory + losize, newmemory,
1028 /* current_mem_size * sizeof(memory_word)); */
1029 (current_mem_size + 1) * sizeof(memory_word));
1030 /* could reduce words moved by (mem_max - mem_end) */
1032 mainmemory = newmemory; /* remember for free later */
1033 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1034 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1035 update_statistics ((int) mainmemory, n,
1036 (current_mem_size + 1) * sizeof (memory_word));
1037 current_mem_size = newsize;
1038 if (current_mem_size != mem_max - mem_start) {
1039 show_line("ERROR: Impossible Memory Error\n", 1);
1041 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1042 else zzzaa = mainmemory;
1043 if (trace_flag) probe_show(); /* 94/Mar/25 */
1049 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1051 int current_font_mem_size=0;
1053 /* fmemoryword can be either halfword or memory_word */
1054 fmemoryword *realloc_font_info (int size)
1055 { /* number of memorywords */
1056 fmemoryword *newfontinfo=NULL;
1058 int newsize=0; /* to quieten compiler */
1059 int n=0; /* to quieten compiler */
1062 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1063 show_line(log_line, 0);
1065 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1066 /* during initial allocation current_font_mem_size == 0 */
1067 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1068 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1069 return font_info; /* pass it back to TeX 99/Fabe/4 */
1071 /* try and prevent excessive frequent reallocations */
1072 /* while avoiding over allocation by too much */
1073 /* minsize = current_font_mem_size / 2; */
1074 minsize = current_font_mem_size / 100 * percent_grow;
1075 if (size < minsize) size = minsize;
1076 if (size < initial_font_mem_size) size = initial_font_mem_size;
1078 for (k=0; k < MAXSPLITS; k++) {
1079 newsize = current_font_mem_size + size;
1080 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1081 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1082 n = (newsize + 1) * sizeof (fmemoryword);
1083 if (trace_flag) trace_memory("font_info", n);
1084 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1085 if (newfontinfo != NULL) break; /* did we get it ? */
1086 if (current_font_mem_size == 0) break; /* initial allocation must work */
1090 if (newfontinfo == NULL) {
1091 memory_error("font", n);
1092 return font_info; /* try and continue !!! */
1094 font_info = newfontinfo;
1096 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1097 show_line(log_line, 0);
1099 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1100 current_font_mem_size = newsize;
1101 if (trace_flag) probe_show(); /* 94/Mar/25 */
1106 #ifdef ALLOCATESTRING
1107 int current_pool_size=0;
1109 packed_ASCII_code *realloc_str_pool (int size)
1114 packed_ASCII_code *newstrpool=NULL;
1117 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1118 show_line(log_line, 0);
1120 if (current_pool_size == pool_size) {
1121 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1123 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1125 /* minsize = current_pool_size / 2; */
1126 minsize = current_pool_size / 100 * percent_grow;
1127 if (size < minsize) size = minsize;
1128 if (size < initial_pool_size) size = initial_pool_size;
1130 for (k = 0; k < MAXSPLITS; k++) {
1131 newsize = current_pool_size + size;
1132 if (newsize > pool_size) newsize = pool_size;
1133 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1134 n = (newsize + 1) * sizeof (packed_ASCII_code);
1135 if (trace_flag) trace_memory("str_pool", n);
1136 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1137 if (newstrpool != NULL) break; /* did we get it ? */
1138 if (current_pool_size == 0) break; /* initial allocation must work */
1139 size = size / 2; /* else can retry smaller */
1142 if (newstrpool == NULL) {
1143 memory_error("string pool", n);
1144 return str_pool; /* try and continue !!! */
1146 str_pool = newstrpool;
1147 update_statistics ((int) str_pool, n, current_pool_size);
1148 current_pool_size = newsize;
1150 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1151 show_line(log_line, 0);
1153 if (trace_flag) probe_show(); /* 94/Mar/25 */
1158 #ifdef ALLOCATESTRING
1159 int current_max_strings=0;
1161 pool_pointer *realloc_str_start (int size)
1166 pool_pointer *newstrstart=NULL;
1169 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1170 show_line(log_line, 0);
1172 if (current_max_strings == max_strings) {
1173 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1175 return str_start; /* pass it back to TeX 99/Fabe/4 */
1177 /* minsize = current_max_strings / 2; */
1178 minsize = current_max_strings / 100 * percent_grow;
1179 if (size < minsize) size = minsize;
1180 if (size < initial_max_strings) size = initial_max_strings;
1182 for (k = 0; k < MAXSPLITS; k++) {
1183 newsize = current_max_strings + size;
1184 if (newsize > max_strings) newsize = max_strings;
1185 /* important + 1 since str_start[maxstring + 1] originally */
1186 n = (newsize + 1) * sizeof (pool_pointer);
1187 if (trace_flag) trace_memory("str_start", n);
1188 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1189 if (newstrstart != NULL) break; /* did we get it ? */
1190 if (current_max_strings == 0) break; /* initial allocation must work */
1191 size = size / 2; /* otherwise can try smaller */
1194 if (newstrstart == NULL) {
1195 memory_error("string pointer", n);
1196 return str_start; /* try and continue */
1198 str_start = newstrstart;
1199 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1200 current_max_strings = newsize;
1202 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1203 show_line(log_line, 0);
1205 if (trace_flag) probe_show(); /* 94/Mar/25 */
1212 /* returns -1 if it fails */
1214 int allocate_ini (int size)
1215 { /* size == trie_size */
1216 int n, nl, no, nc, nr, nh, nt;
1217 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1218 no = (size + 1) * sizeof(trie_op_code);
1219 nc = (size + 1) * sizeof(packed_ASCII_code);
1220 /* nt = (size + 1) * sizeof(bool); */
1221 nt = (size + 1) * sizeof(char);
1222 n = nl + no + nc + nr + nh + nt;
1223 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1224 3 * sizeof(trie_pointer) + sizeof (char)); */
1225 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1226 trie_l = (trie_pointer *) malloc (roundup(nl));
1227 trie_o = (trie_op_code *) malloc (roundup(no));
1228 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1229 trie_r = (trie_pointer *) malloc (roundup(nr));
1230 trie_hash = (trie_pointer *) malloc (roundup(nh));
1231 /* trie_taken = (bool *) malloc (nt); */
1232 trie_taken = (char *) malloc (roundup(nt));
1233 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1234 trie_hash == NULL || trie_taken == NULL) {
1235 memory_error("iniTeX hyphen trie", n);
1236 // exit (1); /* serious error */
1240 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1241 trie_l, trie_o, trie_c);
1242 show_line(log_line, 0);
1243 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1244 trie_r, trie_hash, trie_taken);
1245 show_line(log_line, 0);
1247 update_statistics ((int) trie_l, nl, 0);
1248 update_statistics ((int) trie_o, no, 0);
1249 update_statistics ((int) trie_c, nc, 0);
1250 update_statistics ((int) trie_r, nr, 0);
1251 update_statistics ((int) trie_hash, nh, 0);
1252 update_statistics ((int) trie_taken, nt, 0);
1253 /* trie_size = size; */ /* ??? */
1254 if (trace_flag) probe_show(); /* 94/Mar/25 */
1255 return 0; // success
1259 #ifdef ALLOCATESAVESTACK
1260 int current_save_size=0;
1262 memory_word *realloc_save_stack (int size)
1266 memory_word *newsave_stack=NULL;
1269 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1270 show_line(log_line, 0);
1272 if (current_save_size == save_size) { /* arbitrary limit */
1273 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1275 return save_stack; /* let TeX handle the error */
1277 minsize = current_save_size / 100 * percent_grow;
1278 if (size < minsize) size = minsize;
1279 if (size < initial_save_size) size = initial_save_size;
1281 for (k = 0; k < MAXSPLITS; k++) {
1282 newsize = current_save_size + size;
1283 if (newsize > save_size) newsize = save_size;
1284 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1285 if (trace_flag) trace_memory("save_stack", n);
1286 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1287 if (newsave_stack != NULL) break; /* did we get it ? */
1288 if (current_save_size == 0) break; /* initial allocation must work */
1289 size = size / 2; /* else can retry smaller */
1292 if (newsave_stack == NULL) {
1293 memory_error("save stack", n);
1294 return save_stack; /* try and continue !!! */
1296 save_stack = newsave_stack;
1297 update_statistics ((int) save_stack, n, current_save_size);
1298 current_save_size = newsize;
1300 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1301 show_line(log_line, 0);
1302 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1303 show_line(log_line, 0);
1305 if (trace_flag) probe_show(); /* 94/Mar/25 */
1310 #ifdef ALLOCATEINPUTSTACK
1311 int current_stack_size=0; /* input stack size */
1313 in_state_record *realloc_input_stack (int size)
1317 in_state_record *newinputstack=NULL;
1320 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1321 show_line(log_line, 0);
1323 if (current_stack_size == stack_size) { /* arbitrary limit */
1324 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1328 minsize = current_stack_size / 100 * percent_grow;
1329 if (size < minsize) size = minsize;
1330 if (size < initial_stack_size) size = initial_stack_size;
1332 for (k = 0; k < MAXSPLITS; k++) {
1333 newsize = current_stack_size + size;
1334 if (newsize > stack_size) newsize = stack_size;
1335 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1336 if (trace_flag) trace_memory("input_stack", n);
1337 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1338 if (newinputstack != NULL) break; /* did we get it ? */
1339 if (current_stack_size == 0) break; /* initial allocation must work */
1340 size = size / 2; /* else can retry smaller */
1343 if (newinputstack == NULL) {
1344 memory_error("input stack", n);
1345 return input_stack; /* try and continue !!! */
1347 input_stack = newinputstack;
1348 update_statistics ((int) input_stack, n, current_stack_size);
1349 current_stack_size = newsize;
1351 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1352 show_line(log_line, 0);
1353 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1354 show_line(log_line, 0);
1356 if (trace_flag) probe_show(); /* 94/Mar/25 */
1361 #ifdef ALLOCATENESTSTACK
1362 int current_nest_size=0; /* current nest size */
1364 list_state_record *realloc_nest_stack (int size)
1368 list_state_record *newnest=NULL;
1371 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1372 show_line(log_line, 0);
1374 if (current_nest_size == nest_size) { /* arbitrary limit */
1375 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1377 return nest; /* let TeX handle the error */
1379 minsize = current_nest_size / 100 * percent_grow;
1380 if (size < minsize) size = minsize;
1381 if (size < initial_nest_size) size = initial_nest_size;
1383 for (k = 0; k < MAXSPLITS; k++) {
1384 newsize = current_nest_size + size;
1385 if (newsize > nest_size) newsize = nest_size;
1386 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1387 if (trace_flag) trace_memory("nest stack", n);
1388 newnest = (list_state_record *) REALLOC (nest, n);
1389 if (newnest != NULL) break; /* did we get it ? */
1390 if (current_nest_size == 0) break; /* initial allocation must work */
1391 size = size / 2; /* else can retry smaller */
1394 if (newnest == NULL) {
1395 memory_error("nest stack", n);
1396 return nest; /* try and continue !!! */
1399 update_statistics ((int) nest, n, current_nest_size);
1400 current_nest_size = newsize;
1402 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1403 show_line(log_line, 0);
1404 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1405 show_line(log_line, 0);
1407 if (trace_flag) probe_show(); /* 94/Mar/25 */
1412 #ifdef ALLOCATEPARAMSTACK
1413 int current_param_size=0; /* current param size */
1415 halfword *realloc_param_stack (int size)
1419 halfword *newparam=NULL;
1422 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1423 show_line(log_line, 0);
1425 if (current_param_size == param_size) { /* arbitrary limit */
1426 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1428 return param_stack; /* let TeX handle the error */
1430 minsize = current_param_size / 100 * percent_grow;
1431 if (size < minsize) size = minsize;
1432 if (size < initial_param_size) size = initial_param_size;
1434 for (k = 0; k < MAXSPLITS; k++) {
1435 newsize = current_param_size + size;
1436 if (newsize > param_size) newsize = param_size;
1437 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1438 if (trace_flag) trace_memory("param stack", n);
1439 newparam = (halfword *) REALLOC (param_stack, n);
1440 if (newparam != NULL) break; /* did we get it ? */
1441 if (current_param_size == 0) break; /* initial allocation must work */
1442 size = size / 2; /* else can retry smaller */
1445 if (newparam == NULL) {
1446 memory_error("param stack", n);
1447 return param_stack; /* try and continue !!! */
1449 param_stack = newparam;
1450 update_statistics ((int) param_stack, n, current_param_size);
1451 current_param_size = newsize;
1453 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1454 show_line(log_line, 0);
1455 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1456 show_line(log_line, 0);
1458 if (trace_flag) probe_show(); /* 94/Mar/25 */
1463 #ifdef ALLOCATEBUFFER
1464 int current_buf_size=0;
1466 ASCII_code *realloc_buffer (int size)
1470 ASCII_code *newbuffer=NULL;
1473 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1474 show_line(log_line, 0);
1476 if (current_buf_size == buf_size) { /* arbitrary limit */
1477 /* memory_error ("buffer", buf_size); */
1479 return buffer; /* pass it back to TeX 99/Fabe/4 */
1481 minsize = current_buf_size / 100 * percent_grow;
1482 if (size < minsize) size = minsize;
1483 if (size < initial_buf_size) size = initial_buf_size;
1485 for (k = 0; k < MAXSPLITS; k++) {
1486 newsize = current_buf_size + size;
1487 if (newsize > buf_size) newsize = buf_size;
1488 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1489 if (trace_flag) trace_memory("buffer", n);
1490 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1491 if (newbuffer != NULL) break; /* did we get it ? */
1492 if (current_buf_size == 0) break; /* initial allocation must work */
1493 size = size / 2; /* else can retry smaller */
1496 if (newbuffer == NULL) {
1497 memory_error("buffer", n);
1498 return buffer; /* try and continue !!! */
1501 update_statistics ((int) buffer, n, current_buf_size);
1503 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1505 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1507 current_buf_size = newsize;
1509 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1510 show_line(log_line, 0);
1511 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1512 show_line(log_line, 0);
1514 if (trace_flag) probe_show(); /* 94/Mar/25 */
1519 /* we used to allocate this one only to reduce the size of the PE file */
1520 /* not used anymore - NO advantage */
1522 #ifdef ALLOCATEDVIBUF
1523 eight_bits *allocatedvibuf (int size)
1525 eight_bits *dvi_buf;
1528 n = (size + 1) * sizeof(eight_bits);
1529 if (trace_flag) trace_memory("dvi_buf", n);
1530 dvi_buf = (eight_bits *) malloc (roundup(n));
1531 if (dvi_buf == NULL) {
1532 memory_error("dvi_buf", n);
1536 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1537 show_line(log_line, 0);
1539 update_statistics ((int) dvi_buf, n, 0);
1540 if (trace_flag) probe_show(); /* 94/Mar/25 */
1545 /* we used to allocate this one only to reduce the size of the PE file */
1546 /* it can be done without loss in performance, since register eqtb = zeqtb */
1547 #ifdef ALLOCATEZEQTB
1548 memory_word *allocatezeqtb (int k)
1553 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1554 if (trace_flag) trace_memory("eqtb", n);
1555 zeqtb = (memory_word *) malloc (roundup(n));
1556 if (zeqtb == NULL) {
1557 memory_error("eqtb", n);
1558 // exit (1); /* serious error */
1562 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1563 show_line(log_line, 0);
1565 update_statistics ((int) zeqtb, n, 0);
1566 if (trace_flag) probe_show(); /* 94/Mar/25 */
1571 /* here is the main memory allocation routine -- calls the above */
1572 /* returns -1 if it fails */
1573 /* allocate rather than static 93/Nov/26 */
1574 int allocate_memory (void)
1578 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1582 #error ERROR: Not ready for ALLOCATEHASH...
1585 /* probably not worth while/not a good idea allocating following */
1586 /* they are all rather small, and typically don't need expansion */
1587 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1589 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1590 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1591 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1593 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1594 zzzae = (htwohalves *) malloc (roundup(n));
1596 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1597 zzzae = (twohalves *) malloc (roundup(n));
1599 if (trace_flag) trace_memory("hash table", n);
1600 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1603 memory_error("hash table", n);
1604 // exit (1); /* serious error */
1605 return -1; /* serious error */
1608 n = (inputsize + 1) * sizeof(memory_word);
1609 if (trace_flag) trace_memory("input_stack", n);
1610 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1611 input_stack = (memory_word *) malloc (roundup(n));
1612 if (input_stack == NULL) {
1613 memory_error("input_stack", n);
1614 // exit (1); /* serious error */
1615 return -1; /* serious error */
1619 /* no real reason to allocate dvi_buf - no need to ever grow it */
1620 #ifdef ALLOCATEDVIBUF
1621 /* zdvibuf = NULL; */
1622 zdvibuf = allocatedvibuf (dvi_buf_size);
1623 if (zdvibuf == NULL) return -1;
1626 #ifdef ALLOCATEZEQTB
1628 #ifdef INCREASEFONTS
1629 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1630 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1632 /* zeqtb = allocatezeqtb (13507); */
1633 zeqtb = allocatezeqtb (hash_size + 4007);
1637 #ifdef ALLOCATEINPUTSTACK
1638 input_stack = NULL; /* new 1999/Jan/21 */
1639 current_stack_size = 0;
1640 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1643 #ifdef ALLOCATENESTSTACK
1644 nest = NULL; /* new 1999/Jan/21 */
1645 current_nest_size = 0;
1646 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1649 #ifdef ALLOCATEPARAMSTACK
1650 param_stack = NULL; /* new 1999/Jan/21 */
1651 current_param_size = 0;
1652 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1655 #ifdef ALLOCATESAVESTACK
1656 save_stack = NULL; /* new 1999/Jan/7 */
1657 current_save_size = 0;
1658 save_stack = realloc_save_stack (initial_save_size);
1662 buffer = NULL; /* need to do earlier */
1663 current_buf_size = 0;
1664 buffer = realloc_buffer (initial_buf_size);
1667 #ifdef ALLOCATESTRING
1669 current_pool_size = 0;
1671 current_max_strings = 0;
1672 /* need to create space because iniTeX writes in before reading pool file */
1673 /* for a start, puts in strings for 256 characters */
1674 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1676 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1677 str_pool = realloc_str_pool (initial_pool_size);
1678 str_start = realloc_str_start (initial_max_strings);
1682 /* the following can save a lot of the usual 800k fixed allocation */
1685 current_font_mem_size = 0;
1686 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1687 /* if ini-TeX we need to do it here - no format file read later */
1688 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1694 mem_min = mem_bot; /* just to avoid complaints in texbody */
1695 mem_top = mem_initex;
1697 /* allocate main memory here if this is iniTeX */
1698 /* otherwise wait for format undumping in itex.c ... */
1700 /* avoid this if format specified on command line ??? */
1701 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1702 mem = allocate_main_memory(mem_initex); /* made variable ! */
1705 return -1; /* serious error */
1709 /* now for the hyphenation exception stuff */
1710 #ifdef ALLOCATEHYPHEN
1713 /* this will be overridden later by what is in format file */
1714 hyphen_prime = default_hyphen_prime;
1715 /* non ini-TeX use assumes format will be read and that specifies size */
1718 if (new_hyphen_prime)
1719 hyphen_prime = new_hyphen_prime;
1720 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1725 /* now for memory for the part of the hyphenation stuff that always needed */
1726 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1727 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1728 #ifdef ALLOCATETRIES
1731 if (allocate_tries (trie_size))
1736 /* now for memory for hyphenation stuff needed only when running iniTeX */
1740 if (allocate_ini(trie_size))
1745 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1746 trie_c = NULL; /* (trie_size + 1) * char */
1747 trie_taken = NULL; /* (trie_size + 1) * bool */
1751 free(holeadr); /* create the hole */
1753 return 0; // success
1756 /* returns non-zero if error - done to test integrity of stack mostly */
1757 /* free in reverse order 93/Nov/26 */
1758 int free_memory (void)
1761 unsigned heaptotal=0;
1762 /* unsigned total; */
1764 if (trace_flag) show_line("free_memory ", 0);
1767 if (debug_flag) check_eqtb("free_memory");
1769 if (verbose_flag || trace_flag) show_maximums(stdout);
1771 if (heap_flag) (void) heap_dump(stdout, 1);
1775 heaptotal = (void) heap_dump(stdout, 0);
1777 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1778 heaptotal, max_address);
1779 show_line(log_line, 0);
1782 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1783 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1784 show_line(log_line, 0);
1786 /* following only needed to check consistency of heap ... useful debugging */
1787 if (trace_flag) show_line("Freeing memory again\n", 0);
1790 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1792 /* the following checks the heap integrity */
1794 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1796 #ifdef SHOWHEAPERROR
1798 if (n != _HEAPOK) { /* 94/Feb/18 */
1799 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1800 show_line(log_line, 1);
1801 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1802 show_line(log_line, 0);
1803 return n; /* non-zero and negative */ /* unreachable ??? */
1806 /* only free memory if safe ... additional check */
1809 if (trie_taken != NULL) free(trie_taken);
1810 if (trie_hash != NULL) free(trie_hash);
1811 if (trie_r != NULL) free(trie_r);
1812 if (trie_c != NULL) free(trie_c);
1813 if (trie_o != NULL) free(trie_o);
1814 if (trie_l != NULL) free(trie_l);
1816 trie_hash = trie_l = trie_r = NULL;
1821 #ifdef ALLOCATETRIES
1822 if (trie_trc != NULL) free (trie_trc);
1823 if (trie_tro != NULL) free (trie_tro);
1824 if (trie_trl != NULL) free (trie_trl);
1826 trie_tro = trie_trl = NULL;
1828 #ifdef ALLOCATEHYPHEN
1829 if (hyph_list != NULL) free(hyph_list);
1830 if (hyph_word != NULL) free(hyph_word);
1835 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1836 if (mainmemory != NULL) free(mainmemory);
1840 if (font_info != NULL) free(font_info);
1843 #ifdef ALLOCATESTRING
1844 if (str_start != NULL) free(str_start);
1845 if (str_pool != NULL) free(str_pool);
1851 if (zzzae != NULL) free(zzzae);
1855 #ifdef ALLOCATEDVIBUF
1856 if (zdvibuf != NULL) free(zdvibuf);
1859 #ifdef ALLOCATEZEQTB
1860 if (zeqtb != NULL) free(zeqtb);
1864 #ifdef ALLOCATEPARAMSTACK
1865 if (param_stack != NULL) free(param_stack);
1868 #ifdef ALLOCATENESTSTACK
1869 if (nest != NULL) free(nest);
1872 #ifdef ALLOCATEINPUTSTACK
1873 if (input_stack != NULL) free(input_stack);
1876 #ifdef ALLOCATESAVESTACK
1877 if (save_stack != NULL) free(save_stack);
1880 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1881 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1882 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1883 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1884 format_file = string_file = source_direct = NULL;
1885 if (dvi_file_name != NULL) free(dvi_file_name);
1886 if (log_file_name != NULL) free(log_file_name);
1887 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1894 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1895 if (x % 2 == 0) return false;
1896 for (k = 3; k < x; k = k + 2) {
1897 if (x % k == 0) return false;
1898 /* if (k * k > x) return true; */
1899 if (sum * 4 > x) return true;
1906 bool show_use=false;
1907 bool floating=false;
1909 void complainarg (int c, char *s)
1911 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1912 show_line(log_line, 1);
1913 show_use = 1; // 2000 June 21
1916 /* following is list of allowed command line flags and args */
1918 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1920 /* only 01234567.9 still left to take ... maybe recycle u */
1922 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1924 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1926 void reorderargs (int ac, char **av)
1927 { /* put in 1993/Dec/28 */
1930 // char takeargs[128]; /* large enough for all command line arg chars */
1931 char takeargs[256]; /* large enough for all command line arg chars */
1933 /* assumes arg pointers av[] are writeable */
1934 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1936 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1937 /* show_line("No arguments?\n", 0); */ /* debugging */
1938 return; /* no args ! */
1942 t = takeargs; /* list of those that take args */
1943 while (*s != '\0' && *(s+1) != '\0') {
1944 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1949 show_line(takeargs, 0);
1954 for (;;) { /* scan to end of command line args */
1955 if (*av[n] != '-') break;
1956 /* does it take an argument ? and is this argument next ? */
1958 *(av[n]+2) == '\0' &&
1959 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1960 strchr(takeargs, *(av[n]+1)) != NULL)
1961 n += 2; /* step over it */
1966 for (;;) { /* look for more command line args */
1969 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
1970 while (m < ac && *av[m] != '-') m++; /* first command */
1972 /* does it take an argument ? and is this argument next ? */
1973 /* check first whether the `-x' is isolated, or arg follows directly */
1974 /* then check whether this is one of those that takes an argument */
1976 *(av[m]+2) == '\0' &&
1977 strchr(takeargs, *(av[m]+1)) != NULL) {
1978 s = av[m]; /* move command down before non-command */
1980 for (; m > n; m--) av[m+1] = av[m-1];
1983 n += 2; /* step over moved args */
1986 s = av[m]; /* move command down before non-command */
1987 for (; m > n; m--) av[m] = av[m-1];
1989 n++; /* step over moved args */
1994 int test_align (int address, int size, char *name)
1997 if (size > 4) n = address % 4;
1998 else n = address % size;
2000 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2001 show_line(log_line, 0);
2006 /* activate detailed checking of alignment when trace_flag is set */
2008 void check_fixed_align (int flag)
2010 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2011 show_line("PLEASE RECOMPILE ME!\n", 1);
2013 #ifdef CHECKALIGNMENT
2015 test_align ((int) &mem_top, 4, "mem_top");
2016 test_align ((int) &mem_max, 4, "mem_max");
2017 test_align ((int) &mem_min, 4, "mem_min");
2018 test_align ((int) &bad, 4, "bad");
2019 test_align ((int) &trie_size, 4, "trie_size");
2020 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2021 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2022 test_align ((int) &name_length, 4, "name_length");
2023 test_align ((int) &first, 4, "first");
2024 test_align ((int) &last, 4, "last");
2025 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2026 test_align ((int) &pool_ptr, 4, "pool_ptr");
2027 test_align ((int) &str_ptr, 4, "str_ptr");
2028 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2029 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2030 test_align ((int) &log_file, 4, "log_file");
2031 test_align ((int) &tally, 4, "tally");
2032 test_align ((int) &term_offset, 4, "term_offset");
2033 test_align ((int) &file_offset, 4, "file_offset");
2034 test_align ((int) &trick_count, 4, "trick_count");
2035 test_align ((int) &first_count, 4, "first_count");
2036 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2037 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2038 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2039 test_align ((int) &use_err_help, 4, "use_err_help");
2040 test_align ((int) &interrupt, 4, "interrupt");
2041 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2042 test_align ((int) &arith_error, 4, "arith_error");
2043 test_align ((int) &tex_remainder, 4, "tex_remainder");
2044 test_align ((int) &temp_ptr, 4, "temp_ptr");
2045 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2046 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2047 test_align ((int) &var_used, 4, "var_used");
2048 test_align ((int) &dyn_used, 4, "dyn_used");
2049 test_align ((int) &avail, 4, "avail");
2050 test_align ((int) &mem_end, 4, "mem_end");
2051 test_align ((int) &mem_start, 4, "mem_start");
2052 test_align ((int) &rover, 4, "rover");
2053 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2054 test_align ((int) &depth_threshold, 4, "depth_threshold");
2055 test_align ((int) &breadth_max, 4, "breadth_max");
2056 test_align ((int) &nest, sizeof(nest[0]), "nest");
2059 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2061 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2062 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2063 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2064 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2066 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2067 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2068 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2069 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2070 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2071 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2072 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2073 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2075 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2076 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2077 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2078 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2079 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2080 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2081 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2082 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2083 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2084 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2085 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2086 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2087 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2088 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2089 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2090 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2091 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2092 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2093 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2094 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2095 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2096 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2097 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2098 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2100 #ifdef ALLOCATEDVIBUF
2101 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2103 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2104 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2105 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2106 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2107 test_align ((int) &background, sizeof(background[0]), "background");
2108 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2109 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2110 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2111 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2112 test_align ((int) &hc, sizeof(hc[0]), "hc");
2113 test_align ((int) &hu, sizeof(hu[0]), "hu");
2114 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2115 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2117 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2118 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2119 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2120 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2122 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2123 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2124 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2125 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2126 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2128 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2129 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2130 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2131 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2135 void check_alloc_align (int flag) {
2136 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2137 show_line("PLEASE RECOMPILE ME!\n", 1);
2138 #ifdef CHECKALIGNMENT
2141 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2143 #ifndef ALLOCATEDVIBUF
2144 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2146 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2147 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2148 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2149 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2150 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2151 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2152 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2153 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2154 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2155 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2156 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2157 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2158 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2159 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2160 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2165 void showaddresses (void)
2169 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2170 show_line(log_line, 0);
2171 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2172 show_line(log_line, 0);
2173 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2174 show_line(log_line, 0);
2175 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2176 save_stack, input_stack, line_stack, param_stack);
2177 show_line(log_line, 0);
2178 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2179 font_check, font_size, font_dsize, font_params, font_name);
2180 show_line(log_line, 0);
2181 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2182 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2183 show_line(log_line, 0);
2187 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2189 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2190 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2192 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2193 bool backwardflag = false; /* don't cripple all advanced features */
2194 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2195 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2196 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2197 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2198 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2199 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2200 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2201 bool workingdirectory = false; /* if working directory set in ini */
2203 /* set up full file name for dviwindo.ini and check for [Environment] */
2204 bool setupdviwindo (void)
2206 char dviwindoini[PATH_MAX];
2207 char line[PATH_MAX];
2210 int em = strlen(envsection);
2211 int wm = strlen(wndsection);
2212 int dm = strlen(workdirect);
2216 /* Easy to find Windows directory if Windows runs */
2217 /* Or if user kindly set WINDIR environment variable */
2218 /* Or if running in Windows NT */
2219 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2220 (windir = getenv("WINDIR")) != NULL ||
2221 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2222 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2223 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2224 strcpy(dviwindoini, windir);
2225 strcat(dviwindoini, "\\");
2226 strcat(dviwindoini, inifilename);
2227 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2231 _searchenv (inifilename, "PATH", dviwindoini);
2232 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2235 wndflag = envflag = 0;
2236 /* workingdirectory = false; */
2237 if (*dviwindoini != '\0') {
2238 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2239 /* check whether dviwindo.ini actually has [Environment] section */
2240 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2241 else pinput = _fsopen(dviwindo, "r", share_flag);
2242 if (pinput != NULL) {
2243 while (fgets (line, sizeof(line), pinput) != NULL) {
2244 if (*line == ';') continue;
2245 if (*line == '\n') continue;
2247 if (wndflag && envflag) break; /* escape early */
2249 if (_strnicmp(line, wndsection, wm) == 0) {
2251 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2252 show_line(log_line, 0);
2256 else if (_strnicmp(line, envsection, em) == 0) {
2258 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2259 show_line(log_line, 0);
2261 /* fclose(input); */
2264 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2266 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2267 show_line(log_line, 0);
2269 workingdirectory = true;
2273 (void) fclose(pinput);
2277 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2278 (void) fclose(pinput);
2280 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2281 strcpy(dviwindo, ""); /* failed, for one reason or another */
2286 /* cache to prevent allocating twice in a row */
2288 char *lastname=NULL, *lastvalue=NULL;
2290 /* get value of env var - try first in dviwindo.ini then DOS env */
2291 /* returns allocated string -- these strings are not freed again */
2292 /* is it safe to do that now ? 98/Jan/31 */
2293 char *grabenv (char *varname)
2295 char line[PATH_MAX];
2299 /* int m = strlen(envsection); */
2300 /* int n = strlen(varname); */
2302 if (varname == NULL) return NULL; /* sanity check */
2303 if (*varname == '\0') return NULL; /* sanity check */
2304 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2305 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2306 if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2308 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2309 show_line(log_line, 0);
2311 /* return lastvalue; */ /* save some time here */
2312 return xstrdup(lastvalue);
2313 /* duplicate so can free safely 98/Jan/31 */
2316 /* hmm, following was not xstrdup(...) */ /* not cached */
2317 if (usedviwindo == 0 || *dviwindo == '\0') {
2318 /* return getenv(varname); */
2319 s = getenv(varname);
2320 if (s == NULL) return NULL;
2321 else return xstrdup(s); /* make safe 98/Jan/31 */
2324 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2325 else pinput = _fsopen(dviwindo, "r", share_flag);
2327 if (pinput != NULL) {
2328 m = strlen(envsection);
2329 /* search for [Environment] section */ /* should be case insensitive */
2330 while (fgets (line, sizeof(line), pinput) != NULL) {
2331 if (*line == ';') continue;
2332 if (*line == '\n') continue;
2333 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2334 /* search for varname=... */ /* should be case sensitive ? */
2335 n = strlen(varname);
2336 while (fgets (line, sizeof(line), pinput) != NULL) {
2337 if (*line == ';') continue;
2338 if (*line == '[') break;
2339 /* if (*line == '\n') break; */ /* ??? */
2340 if (*line <= ' ') continue; /* 95/June/23 */
2341 /* if (strncmp(line, varname, n) == 0 && */
2342 if (_strnicmp(line, varname, n) == 0 &&
2343 *(line+n) == '=') { /* found it ? */
2344 (void) fclose (pinput);
2345 /* flush trailing white space */
2346 s = line + strlen(line) - 1;
2347 while (*s <= ' ' && s > line) *s-- = '\0';
2348 if (trace_flag) { /* DEBUGGING ONLY */
2349 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2350 show_line(log_line, 0);
2353 if (lastname != NULL) free(lastname);
2354 lastname = xstrdup (varname);
2355 if (lastvalue != NULL) free(lastvalue);
2356 lastvalue = xstrdup(s);
2357 return xstrdup(s); /* 98/Jan/31 */
2358 } /* end of matching varname */
2359 } /* end of while fgets */
2360 /* break; */ /* ? not found in designated section */
2361 } /* end of search for [Environment] section */
2363 (void) fclose (pinput);
2364 } /* end of if fopen */
2365 s = getenv(varname); /* failed, so try and get from environment */
2366 /* if (s != NULL) return s; */
2368 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2369 if (lastname != NULL) free(lastname);
2370 lastname = xstrdup (varname);
2371 if (lastvalue != NULL) free(lastvalue);
2372 lastvalue = xstrdup(s); /* remember in case asked again ... */
2374 return xstrdup(s); /* 98/Jan/31 */
2376 else return NULL; /* return NULL if not found anywhere */
2379 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2381 void flush_trailing_slash (char *directory)
2384 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2385 if (strcmp(directory, "") != 0) {
2386 s = directory + strlen(directory) - 1;
2387 if (*s == '\\' || *s == '/') *s = '\0';
2391 void knuthify (void)
2393 /* show_current = false; */ /* show ultimate limits */
2394 /* reorder_arg_flag = false; */ /* don't reorder command line */
2395 /* deslash = false; */ /* don't unixify file names */
2396 /* return_flag = false; */ /* don't allow just ^^M termination */
2397 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2398 restrict_to_ascii = false; /* don't complain non ASCII */
2399 allow_patterns = false; /* don't allow pattern redefinition */
2400 show_in_hex = true; /* show character code in hex */
2401 show_in_dos = false; /* redundant with previous */
2402 show_numeric = false; /* don't show character code decimal */
2403 show_missing = false; /* don't show missing characters */
2404 civilize_flag = false; /* don't reorder date fields */
2405 c_style_flag = false; /* don't add file name to error msg */
2406 show_fmt_flag = false; /* don't show format file in log */
2407 show_tfm_flag = false; /* don't show metric file in log */
2408 /* font_max = 255; */ /* revert to TeX 82 limit */
2409 /* if you want this, change in tex.h definition of font_max to `int' */
2410 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2412 show_line_break_stats = false; /* do not show line break stats */
2413 show_fonts_used = false;
2414 default_rule = 26214; /* revert to default rule thickness */
2415 pseudo_tilde = false;
2416 pseudo_space = false;
2417 show_texinput_flag = false;
2418 truncate_long_lines = false;
2419 allow_quoted_names = false;
2420 show_cs_names = false;
2421 font_dimen_zero = false; /* 98/Oct/5 */
2422 ignore_frozen = false; /* 98/Oct/5 */
2423 suppress_f_ligs = false; /* 99/Jan/5 */
2424 full_file_name_flag = false; // 00 Jun 18
2425 save_strings_flag = false; // 00 Aug 15
2426 knuth_flag = true; /* so other code can know about this */
2427 } /* end of knuthify */
2429 /* following have already been used up */
2431 /* abcdefghijklmnopqrstuvwxyz */
2433 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2437 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2439 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2441 /* following made global so analyze_flag can be made separate procedure */
2443 // char *xchrfile=""; /* save space use xstrdup */
2444 char *xchrfile = NULL; /* save space use xstrdup */
2445 // char *replfile="";/* save space use xstrdup */
2446 char *replfile = NULL;/* save space use xstrdup */
2448 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2450 /* analyze command line flag or argument */
2451 /* c is the flag letter itself, while optarg is start of arg if any */
2453 /* when making changes, revise allowedargs */
2456 int analyze_flag (int c, char *optarg)
2461 want_version = true;
2462 verbose_flag = true;
2468 interaction = batch_mode; /* quiet mode */
2471 interaction = nonstop_mode; /* run mode */
2474 interaction = scroll_mode; /* scroll mode */
2477 interaction = error_stop_mode; /* tex mode */
2480 backwardflag = true; /* 94/Jun/15 */
2481 knuthify(); /* revert to `standard' Knuth TeX */
2484 c_style_flag = true; /* C style error msg 94/Mar/21 */
2487 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2490 current_tfm = false; /* not look current dir for TFM */
2493 current_flag = false; /* not look current dir for files */
2496 show_missing = false; /* do not show missing 94/June/10 */
2499 deslash = false; /* flipped 93/Nov/18 */
2500 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2503 allow_patterns = true; /* 93/Nov/26 */
2504 /* reset_exceptions = true; */ /* 93/Dec/23 */
2506 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2508 show_in_hex = true; /* flipped 00/Jun/18 */
2511 show_in_dos = true; /* 96/Jan/26 */
2514 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2517 workingdirectory = true; /* use source dir 98/Sep/29 */
2520 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2523 show_fonts_used = false; /* 97/Dec/24 */
2526 shorten_file_name = true; /* 95/Feb/20 */
2529 show_cs_names = true; /* 98/Mar/31 */
2532 ignore_frozen = true; /* 98/Oct/5 */
2535 font_dimen_zero = false; /* 98/Oct/5 */
2538 show_texinput_flag = false; /* 98/Jan/28 */
2540 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2543 usedviwindo = false; /* 94/May/19 */
2546 show_line_break_stats = false; /* 96/Feb/8 */
2549 show_fmt_flag = false; /* 94/Jun/21 */
2552 format_specific = false; /* 95/Jan/7 */
2555 encoding_specific = false; /* 98/Oct/5 */
2558 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2560 /* following are pretty obscure */
2561 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2563 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2565 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2568 full_file_name_flag = false; // 00 Jun 18
2571 save_strings_flag = false; // 00 Aug 15
2573 /* following are unannounced options */ /* some may be recycled ... */
2578 quitflag++; /* 93/Dec/16 */
2580 /* The following are really obscure and should not be advertized */
2582 show_current = false; /* tex8 93/Dec/14 */
2585 show_numeric = false; /* 93/Dec/21 */
2588 civilize_flag = false; /* 93/Dec/16 */
2591 open_trace_flag = true; /* openinou 1994/Jan/8 */
2594 reorder_arg_flag = false; /* local */
2597 test_dir_access = false; /* 94/Feb/10 */
2600 dir_method = false; /* 94/Feb/10 */
2603 file_method = false; /* 94/Feb/13 */
2605 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2606 /* case 'X': nohandler++; break; */
2607 /* case 'f': waitflush = false; break; */
2608 /* case 'F': floating = true; break; */
2609 /* *********** following command line options take arguments ************** */
2612 mem_initex = mem_top;
2614 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2615 if (mem_initex == 0)
2616 complainarg(c, optarg);
2619 #ifdef VARIABLETRIESIZE
2622 trie_size = default_trie_size;
2624 trie_size = atoi(optarg); /* 93 Dec/1 */
2626 complainarg(c, optarg);
2629 #ifdef ALLOCATEHYPHEN
2632 new_hyphen_prime = hyphen_prime * 2;
2634 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2635 if (new_hyphen_prime == 0)
2636 complainarg(c, optarg);
2639 #ifdef ALLOCATEDVIBUF
2642 dvi_buf_size = default_dvi_buf_size;
2644 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2645 if (dvi_buf_size == 0)
2646 complainarg(c, optarg);
2653 percent_grow = atoi(optarg); /* 93/Dec/11 */
2654 if (percent_grow == 0)
2655 complainarg(c, optarg);
2661 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2662 if (pseudo_tilde > 255)
2664 else if (pseudo_tilde < 128)
2667 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2668 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2674 tab_step = atoi(optarg); /* 94/July/3 */
2676 complainarg(c, optarg);
2680 xchrfile = xstrdup("xchr.map");
2682 xchrfile = xstrdup(optarg);
2683 if (xchrfile == NULL || *xchrfile == '\0')
2684 complainarg(c, optarg);
2688 replfile = xstrdup("repl.key");
2690 replfile = xstrdup(optarg);
2691 if (replfile == NULL || *replfile == '\0')
2692 complainarg(c, optarg);
2694 /* more obscure stuff - ppssibly recycle */
2697 default_rule = 26214; /* 95/Oct/9 */
2699 default_rule = atoi(optarg); /* 95/Oct/9 */
2700 if (default_rule == 0)
2701 complainarg(c, optarg);
2707 complainarg(c, optarg);
2713 dvi_directory = xstrdup(optarg);
2714 if (strcmp(dvi_directory, "") == 0)
2715 complainarg(c, optarg);
2721 log_directory = xstrdup(optarg);
2722 if (strcmp(log_directory, "") == 0)
2723 complainarg(c, optarg);
2729 aux_directory = xstrdup(optarg);
2730 if (strcmp(aux_directory, "") == 0)
2731 complainarg(c, optarg);
2736 return -1; // failed to recognize
2742 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2743 //char *yytexcmd="yandytex.cmd";
2744 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2746 /* Try and read default command file - YANDYTEX.CMD */
2747 /* in current directory and then in directory of YANDYTEX */
2748 /* (does not make sense in TeX file directory) */
2749 /* since we don't yet know where that is ! */
2750 /* can't conveniently include this in output file either - not open yet */
2752 /* used both for yytex.cmd and @ indirect command line files */
2753 /* can this be reentered ? */
2755 /* supply extension if none */
2756 void yy_extension (char *fname, char *ext)
2759 if ((s = strrchr(fname, '.')) == NULL ||
2760 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2766 /* remove file name - keep only path - inserts '\0' to terminate */
2768 void strip_name (char *pathname)
2771 if ((s = strrchr(pathname, '\\')) != NULL);
2772 else if ((s = strrchr(pathname, '/')) != NULL);
2773 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2778 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2780 char *programpath = ""; /* pathname of program */
2781 /* redundant with texpath ? */
2783 /* The following does not deslashify arguments ? Do we need to ? */
2785 int read_commands (char *filename)
2787 char commandfile[PATH_MAX];
2789 char line[PATH_MAX];
2790 char *linedup; /* need to copy line to preserve args */
2796 /* Try first in current directory (or use full name as specified) */
2797 strcpy(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 /* If that fails, try in YANDYTeX program directory */
2805 strcpy(commandfile, programpath);
2806 /* don't need fancy footwork, since programpath non-empty */
2807 strcat(commandfile, "\\");
2808 strcat(commandfile, filename);
2809 yy_extension(commandfile, "cmd");
2810 if (share_flag == 0)
2811 command = fopen(commandfile, "r");
2813 command = _fsopen(commandfile, "r", share_flag);
2814 if (command == NULL) {
2815 /* perrormod(commandfile); */ /* debugging only */
2816 /* strcpy(commandfile, ""); */ /* indicate failed */
2817 return 0; /* no command line file YYTEX.CMD */
2821 /* allow for multiple lines --- ignore args that don't start with `-' */
2822 while (fgets(line, PATH_MAX, command) != NULL) {
2823 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2824 /* skip over comment lines and blank lines */
2825 if (*line == '%' || *line == ';' || *line == '\n') continue;
2826 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2827 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2828 linedup = xstrdup (line); /* 93/Nov/15 */
2829 if (linedup == NULL) {
2830 show_line("ERROR: out of memory\n", 1); /* read_commands */
2832 return -1; // failure
2834 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2836 if (*s == '-' || *s == '/') {
2839 /* if (*optarg = '=') optarg++; */
2840 if (*optarg == '=') optarg++;
2841 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2843 /* else break; */ /* ignore non-flag items */
2844 s = strtok(NULL, " \t\n\r"); /* go to next token */
2846 /* If you want to see command lines in file - put -v in the file */
2847 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2849 (void) fclose(command); /* no longer needed */
2850 return 1; // success
2853 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2855 /* try and read commands on command line */
2856 int read_command_line (int ac, char **av)
2859 char *optargnew; /* equal to optarg, unless that starts with `=' */
2860 /* in which case it is optarg+1 to step over the `=' */
2861 /* if optarg = 0, then optargnew = 0 also */
2863 // show_line("read_command_line\n", 0);
2864 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2866 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2867 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2868 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2869 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2870 if (optarg != 0 && *optarg == '=')
2871 optargnew = optarg+1;
2874 analyze_flag (c, optargnew);
2876 if (show_use || quitflag == 3) {
2877 // showversion (stdout);
2879 strcat(log_line, "\n");
2880 show_line(log_line, 0);
2881 stampcopy(log_line);
2882 strcat(log_line, "\n");
2883 show_line(log_line, 0);
2884 if (show_use) show_usage(av[0]);
2885 else if (quitflag == 3) {
2886 strcat(log_line, "\n");
2887 show_line(log_line, 0);
2890 return -1; // failure
2893 if (floating) testfloating(); /* debugging */
2896 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2897 if (read_xchr_file(replfile, 1, av)) {
2898 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2902 /* key_replace used in texmf.c (input_line) */
2903 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2904 if (read_xchr_file(xchrfile, 0, av)) {
2905 if (trace_flag) show_line("NON ASCII ON\n", 0);
2909 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2910 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2915 void uppercase (char *s)
2918 while ((c = *s) != '\0') {
2919 /* if (islower(c)) *s = toupper (*s); */
2926 int init_commands (int ac, char **av)
2928 /* NOTE: some defaults changed 1993/Nov/18 */
2929 /* want_version = show_use = switchflag = return_flag = false;
2930 is_initex = trace_flag = deslash = non_ascii = false; */
2931 is_initex = false; /* check for dumping format file */
2932 allow_patterns = false; /* using \pattern after format file loaded */
2933 reset_exceptions = false;
2935 key_replace = false;
2936 want_version = false;
2937 open_trace_flag = false;
2939 verbose_flag = false;
2941 restrict_to_ascii = false;
2942 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2943 show_in_dos = false; /* default is not to translate to DOS 850 */
2944 return_flag = true; // hard wired now
2945 trimeof = true; // hard wired now
2947 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2948 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2949 default_rule = 26214; /* default rule variable 95/Oct/9 */
2950 show_current = true;
2951 civilize_flag = true;
2952 show_numeric = true;
2953 show_missing = true;
2954 current_flag = true;
2955 current_tfm = true; /* search for TFMs in current dir as well */
2956 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2957 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2958 file_method = true; /* use file_p (_findfirst) not readable (access) */
2959 /* waitflush = true; */ /* flushed 97/Dec/24 */
2960 c_style_flag = false; /* use c-style error output */
2961 show_fmt_flag = true; /* show format file in log */
2962 show_tfm_flag = false; /* don't show metric file in log */
2963 shorten_file_name = false; /* don't shorten file names to 8+3 */
2964 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2965 truncate_long_lines = true; /* truncate long lines */
2966 tab_step = 0; /* do not replace tabs with spaces */
2967 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2968 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2969 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2970 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2971 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2972 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2973 knuth_flag = false; /* allow extensions to TeX */
2974 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2975 full_file_name_flag = true; /* new default 2000 June 18 */
2976 save_strings_flag = true; // 2000 Aug 15
2977 errout = stdout; /* as opposed to stderr say --- used ??? */
2978 abort_flag = 0; // not yet hooked up ???
2979 err_level = 0; // not yet hooked up ???
2980 new_hyphen_prime = 0;
2981 #ifdef VARIABLETRIESIZE
2982 /* trie_size = default_trie_size; */
2988 #ifdef ALLOCATEDVIBUF
2991 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2992 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2993 share_flag = 0; /* revert to fopen for now */
2995 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2996 programpath = xstrdup(av[0]); /* extract path executable */
2997 strip_name(programpath); /* strip off yandytex.exe */
2999 //format_name = "yandytex";
3000 format_name = "plain"; /* format name if specified on command line */
3004 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
3005 return -1; // in case of error
3007 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
3008 return -1; // in case of error
3010 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
3012 /* Print version *after* banner ? */ /* does this get in log file ? */
3014 // showversion (stdout);
3015 // showversion (log_line);
3017 strcat(log_line, "\n");
3018 show_line(log_line, 0);
3019 stampcopy(log_line);
3020 strcat(log_line, "\n");
3021 show_line(log_line, 0);
3023 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
3025 /* if we aren't including current directory in any directory lists */
3026 /* then makes no sense to avoid them separately for TFM files ... */
3027 /* (that is, the ./ is already omitted from the dir list in that case */
3028 if (!current_flag && !current_tfm)
3029 current_tfm = true; /* 94/Jan/24 */
3030 return 0; // success
3033 /* E sets environment variable ? */
3035 void initial_memory (void)
3037 /* set initial memory allocations */
3038 if (mem_extra_high < 0)
3040 if (mem_extra_low < 0)
3046 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3047 if (mem_extra_high != 0 || mem_extra_low != 0)
3049 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3050 mem_extra_high = 0; mem_extra_low = 0;
3056 if (mem_initex != 0)
3058 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3063 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3064 /* trie_size = 0; */
3067 if (mem_initex == 0)
3068 mem_initex = default_mem_top;
3070 trie_size = default_trie_size;
3071 /* Just in case user mistakenly specified words instead of kilo words */
3072 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3073 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3074 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3075 #ifdef ALLOCATEHIGH /* not used anymore */
3076 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3077 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3078 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3081 #ifdef ALLOCATELOW /* not used anymore */
3082 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3083 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3084 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3087 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3088 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3089 /* mem_initex = 2048 * 1024; */
3091 #ifdef ALLOCATEDVIBUF
3092 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3093 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3094 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3095 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3096 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3098 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3099 if (new_hyphen_prime > 0) {
3101 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3103 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3104 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3106 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3107 show_line(log_line, 0);
3111 if (percent_grow > 100) percent_grow = percent_grow - 100;
3112 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3113 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3116 /**********************************************************************/
3118 void perrormod (char *s)
3120 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3121 show_line(log_line, 1);
3127 fflush(stdout); /* ??? */
3128 fflush(stderr); /* ??? */
3129 (void) _getch(); /* ??? */
3133 void checkpause (int flag)
3136 int debug_pause = 0;
3137 /* don't stop if in Q (quiet) or R (run) mode */
3138 /* stop only in S (scroll) and T (TeX) mode */
3139 if (interaction >= 0 && interaction < 2)
3140 flag = 0; /* 98/Jun/30 */
3141 s = grabenv("DEBUGPAUSE");
3142 if (s != NULL) sscanf(s, "%d", &debug_pause);
3143 if (flag < 0) return;
3145 if (debug_pause || flag > 0) {
3148 show_line("Press any key to continue . . .\n", 0);
3155 void check_enter (int argc, char *argv[])
3158 char current[FILENAME_MAX];
3159 if (grabenv("DEBUGPAUSE") != NULL) {
3160 (void) _getcwd(current, sizeof(current));
3161 sprintf(log_line, "Current directory: `%s'\n", current);
3162 show_line(log_line, 0);
3163 for (m = 0; m < argc; m++) {
3164 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3165 show_line(log_line, 0);
3172 void checkexit (int n)
3179 /*************************************************************************/
3181 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3182 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3183 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3184 /* this is then undone in tex3.c both for fopen input and output */
3185 /* not ideal, since pseudo name appears in log and in error messages ... */
3187 void hidetwiddle (char *name)
3192 sprintf(log_line, "Hidetwiddle %s", name);
3193 show_line(log_line, 0);
3196 /* while (*s != '\0' && *s != ' ') { */
3197 while (*s != '\0') {
3198 if (*s == '~' && pseudo_tilde != 0)
3199 *s = (char) pseudo_tilde; /* typically 254 */
3200 else if (*s == ' ' && pseudo_space != 0)
3201 *s = (char) pseudo_space; /* typically 255 */
3206 sprintf(log_line, "=> %s\n", name);
3207 show_line(log_line, 0);
3212 void deslash_all (int ac, char **av)
3214 char buffer[PATH_MAX];
3217 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3218 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3220 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3222 check_enter(ac, av); /* 95/Oct/28 */
3224 /* environment variables for output directories (as in PC TeX) */
3226 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3227 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3228 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3230 strcpy(buffer, av[0]); /* get path to executable */
3231 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3232 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3233 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3234 s = buffer + strlen(buffer) - 1;
3235 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3236 texpath = xstrdup(buffer);
3238 /* Hmm, we may be operating on DOS environment variables here !!! */
3240 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3241 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3242 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3245 unixify (texpath); /* 94/Jan/25 */
3246 /* if output directories given, deslashify them also 1993/Dec/12 */
3247 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3248 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3249 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3252 /* deslash TeX source file (and format, if format specified) */
3253 /* and check args to see whether format was specified */
3255 /* NOTE: assuming that command line arguments are in writable memory ! */
3256 /* if (trace_flag || debug_flag)
3257 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3258 /* if (optind < ac) { */ /* bkph */
3259 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3261 if (trace_flag || debug_flag) {
3262 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3263 optind, av[optind], ac);
3264 show_line(log_line, 0);
3266 unixify(av[optind]);
3268 if (pseudo_tilde != 0 || pseudo_space != 0)
3269 hidetwiddle (av[optind]); /* 95/Sep/25 */
3270 /* For Windows NT, lets allow + instead of & for format specification */
3271 if (*av[optind] == '&' || *av[optind] == '+') {
3272 format_spec = 1; /* format file specified */
3273 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3274 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3275 if (optind + 1 < ac) {
3277 if (trace_flag || debug_flag) {
3278 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3279 optind+1, av[optind+1], ac);
3280 show_line(log_line, 0);
3282 unixify(av[optind+1]);
3284 if (pseudo_tilde != 0 || pseudo_space != 0)
3285 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3291 /* The above seems to assume that arguments that don't start with '-' */
3292 /* are file names or format names - what if type in control sequences? */
3294 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3296 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3297 /* interaction == 1 => nonstop mode (omit all stops) */
3298 /* interaction == 2 => scroll mode (omit error stops) */
3299 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3301 /* main entry point follows */
3303 /* this gets called pretty much right away in `main' in texmf.c */
3305 /* note: those optarg == 0 test don't really work ... */
3306 /* note: optarg starts at = in case of x=... */
3308 int init (int ac, char **av)
3310 char initbuffer[PATH_MAX];
3313 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3320 show_line("TEXDEBUG\n", 0);
3321 trace_flag = 1; /* 94/April/14 */
3324 if (sizeof(memory_word) != 8) { /* compile time test */
3325 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3326 show_line(log_line, 1);
3329 start_time = clock(); /* get time */
3330 main_time = start_time; /* fill in, in case file never opened */
3332 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3334 /* reset all allocatable memory pointers to NULL - in case we drop out */
3339 #ifdef ALLOCATEZEQTB
3345 #ifdef ALLOCATESAVESTACK
3348 #ifdef ALLOCATEDVIBUF
3351 #ifdef ALLOCATEBUFFER
3352 buffer = NULL; /* new 1999/Jan/7 need to do early */
3353 current_buf_size = 0;
3354 buffer = realloc_buffer (initial_buf_size);
3355 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3357 hyph_list = NULL; hyph_word = NULL;
3358 trie_taken = NULL; trie_hash = NULL;
3367 log_opened = false; /* so can tell whether opened */
3368 interaction = -1; /* default state => 3 */
3369 missing_characters = 0; /* none yet! */
3370 workingdirectory = false; /* set from dviwindo.ini & command line */
3371 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3372 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3373 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3374 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3375 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3377 if (reorder_arg_flag) reorderargs(ac, av);
3379 if (init_commands(ac, av))
3380 return -1; // failure
3382 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3384 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3385 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3386 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3387 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3388 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3390 first_pass_count = 0;
3391 second_pass_count = 0;
3392 final_pass_count = 0;
3393 paragraph_failed = 0;
3400 closed_already=0; // so can only do once
3402 if (trace_flag) show_line("Entering init (local)\n", 0);
3404 /* Print version *after* banner ? */ /* does this get in log file ? */
3406 probe_memory(); /* show top address */
3407 ini_max_address = max_address; /* initial max address */
3408 if (trace_flag) show_maximums(stdout);
3410 if (heap_flag) (void) heap_dump(stdout, 1);
3415 deslash_all(ac, av); /* deslash and note if format specified */
3417 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3421 if (format_spec && mem_spec_flag) {
3422 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3425 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3426 return -1; // if failed to allocate
3428 /* following is more or less useless since most all things not yet alloc */
3429 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3431 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3435 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3438 if (trace_flag) show_line("Leaving init (local)\n", 0);
3439 return 0; // success
3442 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3444 /* void show_inter_val (clock_t start, clock_t end) { */
3445 void show_inter_val (clock_t interval)
3447 /* clock_t interval; */
3448 /* int seconds, tenths; */
3449 /* int seconds, tenths, hundredth; */
3450 int seconds, tenths, hundredth, thousands;
3451 /* interval = end - start; */
3452 /* sanity check whether positive ? */
3453 if (interval >= CLK_TCK * 10) {
3454 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3455 seconds = tenths / 10;
3456 tenths = tenths % 10;
3457 sprintf(log_line, "%d.%d", seconds, tenths);
3458 show_line(log_line, 0);
3460 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3461 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3462 seconds = hundredth / 100;
3463 hundredth = hundredth % 100;
3464 sprintf(log_line, "%d.%02d", seconds, hundredth);
3465 show_line(log_line, 0);
3467 else if (interval > 0) { /* 94/Oct/4 */
3468 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3469 seconds = thousands / 1000;
3470 thousands = thousands % 1000;
3471 sprintf(log_line, "%d.%03d", seconds, thousands);
3472 show_line(log_line, 0);
3474 else show_line("0", 0); /* 95/Mar/1 */
3477 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3478 /* shows various times, warning about missing chars */
3480 int endit (int flag)
3483 finish_time = clock();
3484 if (missing_characters != 0) flag = 1;
3485 if (missing_characters) {
3487 "! There %s %d missing character%s --- see log file\n",
3488 (missing_characters == 1) ? "was" : "were", missing_characters,
3489 (missing_characters == 1) ? "" : "s");
3490 show_line(log_line, 0);
3492 if (free_memory() != 0) flag++;
3494 /* show per page time also ? */
3496 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3497 start_time, main_time, finish_time); */
3498 show_line("Total ", 0);
3499 /* show_inter_val(start_time, finish_time); */
3500 show_inter_val(finish_time - start_time);
3501 show_line(" sec (", 0);
3502 /* show_inter_val(start_time, main_time); */
3503 show_inter_val(main_time - start_time);
3504 show_line(" format load + ", 0);
3505 /* show_inter_val(main_time, finish_time); */
3506 show_inter_val(finish_time - main_time);
3507 show_line(" processing) ", 0);
3508 if (total_pages > 0) {
3509 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3510 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3511 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3512 show_inter_val ((finish_time - main_time) / total_pages);
3513 show_line(" sec per page", 0);
3523 /********************************************************************************/
3525 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3529 #define MAXCOLUMN 78
3531 void print_cs_name (FILE *output, int h)
3536 textof = hash[h].v.RH;
3537 if (textof == 0) return; /* ignore if text() == 0 */
3539 if (textcolumn != 0) {
3540 sprintf(log_line, ", ");
3541 if (output != NULL) fprintf(output, log_line);
3542 else show_line(log_line, 0);
3545 if (textcolumn + n + 2 >= MAXCOLUMN) {
3546 sprintf(log_line, "\n");
3547 if (output == stderr) show_line(log_line, 1);
3548 else if (output == stdout) show_line(log_line, 0);
3549 else fputs(log_line, output);
3553 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3556 if (output == stderr) show_line(log_line, 1);
3557 else if (output == stdout) show_line(log_line, 0);
3558 else fprintf(output, log_line);
3562 int compare_strn (int, int, int, int); /* in tex9.c */
3564 /* compare two csnames in qsort */
3566 int compare_cs (const void *cp1, const void *cp2)
3568 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3571 textof1 = hash[c1].v.RH;
3572 textof2 = hash[c2].v.RH;
3573 l1 = length(textof1);
3574 l2 = length(textof2);
3575 k1 = str_start[textof1];
3576 k2 = str_start[textof2];
3577 /* showstring (k1, l1); */
3578 /* showstring (k2, l2); */
3579 return compare_strn (k1, l1, k2, l2);
3584 /* Allocate table of indeces to allow sorting on csname */
3585 /* Allocate flags to remember which ones already listed at start */
3587 void print_cs_names (FILE *output, int pass)
3589 int h, k, ccount, repeatflag;
3591 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3593 if (pass == 0 && csused == NULL) {
3594 csused = (char *) malloc (nfcs);
3595 if (csused == NULL) return;
3597 memset(csused, 0, nfcs);
3599 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3604 for (h = hash_base + 1; h < nfcs; h++) {
3605 if (pass == 1 && csused[h]) continue;
3606 if (hash[h].v.RH != 0) {
3607 if (pass == 0) csused[h] = 1;
3612 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3613 ccount, (pass == 1) ? "new" : "");
3614 if (output == stderr) show_line(log_line, 1);
3615 else if (output == stdout) show_line(log_line, 0);
3616 else fprintf(output, log_line);
3618 if (ccount > 0) { /* don't bother to get into trouble */
3620 cnumtable = (int *) malloc (ccount * sizeof(int));
3621 if (cnumtable == NULL) return;
3624 /* for (h = 515; h < (hash_size + 780); h++) { */
3625 for (h = hash_base+1; h < nfcs; h++) {
3626 if (pass == 1 && csused[ h]) continue;
3627 if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3630 qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3633 for (k = 0; k < ccount; k++) {
3635 if (pass == 1 && csused[ h]) continue;
3636 print_cs_name(output, h);
3638 sprintf(log_line, "\n");
3639 if (output == stderr) show_line(log_line, 1);
3640 else if (output == stdout) show_line(log_line, 0);
3641 else fprintf(output, log_line);
3642 free((void *)cnumtable);
3645 if (pass == 1 && csused != NULL) {
3651 /***************** font info listing moved from TEX9.C ******************/
3653 void showstring (int k, int l)
3656 while (l-- > 0) *s++ = str_pool[k++];
3659 show_line(log_line, 0);
3662 /* compare two strings in str_pool (not null terminated) */
3663 /* k1 and k2 are positions in string pool */
3664 /* l1 and l2 are lengths of strings */
3666 int compare_strn (int k1, int l1, int k2, int l2)
3669 /* while (l1-- > 0 && l2-- > 0) { */
3670 while (l1 > 0 && l2 > 0) {
3673 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3674 if (c1 > c2) return 1;
3675 else if (c2 > c1) return -1;
3679 if (l1 > 0) return 1; /* first string longer */
3680 else if (l2 > 0) return -1; /* second string longer */
3681 return 0; /* strings match */
3684 /* compare two font names and their at sizes in qsort */
3686 int compare_fnt (const void *fp1, const void *fp2)
3688 int f1, f2, l1, l2, k1, k2, s;
3691 l1 = length(font_name[f1]);
3692 l2 = length(font_name[f2]);
3693 k1 = str_start[font_name[f1]];
3694 k2 = str_start[font_name[f2]];
3695 /* showstring (k1, l1); */
3696 /* showstring (k2, l2); */
3697 s = compare_strn (k1, l1, k2, l2);
3698 /* sprintf(log_line, "%d\n", s); */
3699 if (s != 0) return s;
3700 if (font_size[f1]> font_size[f2]) return 1;
3701 else if (font_size[f1]< font_size[f2]) return -1;
3702 return 0; /* should not ever get here */
3705 /* compare two font names */
3707 int compare_fnt_name (int f1, int f2)
3709 int l1, l2, k1, k2, s;
3710 l1 = length(font_name[f1]);
3711 l2 = length(font_name[f2]);
3712 k1 = str_start[font_name[f1]];
3713 k2 = str_start[font_name[f2]];
3714 /* showstring (k1, l1); */
3715 /* showstring (k2, l2); */
3716 s = compare_strn (k1, l1, k2, l2);
3717 /* sprintf(log_line, "%d\n", s); */
3721 /* decode checksum information */
3723 unsigned long checkdefault = 0x59265920; /* default signature */
3725 int decode_fourty (unsigned long checksum, char *codingvector)
3729 /* char codingvector[6+1]; */
3731 /* if (checksum == checkdefault) { */
3732 if (checksum == 0) {
3733 /* strcpy(codingvector, "unknown"); */
3734 strcpy(codingvector, "unknwn");
3737 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3738 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3739 strcpy (codingvector, "fixed "); /* if not specified ... */
3740 return 1; /* no info available */
3743 for (k = 0; k < 6; k++) {
3744 c = (int) (checksum % 40);
3745 checksum = checksum / 40;
3746 if (c <= 'z' - 'a')c = c + 'a';
3747 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3748 else if (c == 36) c = '-';
3749 else if (c == 37) c = '&';
3750 else if (c == 38) c = '_';
3751 else c = '.'; /* unknown */
3752 codingvector[5-k] = (char) c;
3754 codingvector[6] = '\0';
3756 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3757 return 0; /* encoding info returned in codingvector */
3760 double sclpnt (long x)
3763 pt = (double) x / 65536.0;
3764 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3768 // Shows list of fonts in log file
3770 void dvi_font_show(internal_font_number f, int suppressname)
3772 int a, l, k, n, for_end;
3773 unsigned long checksum;
3774 char checksumvector[8];
3777 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3778 /* fprintf (log_file, "%d ", suppressname); */
3779 /* suppressname = 0; */
3780 putc(' ', log_file);
3781 if (suppressname == 0) {
3782 a = length(font_area[f]);
3783 l = length(font_name[f]);
3784 k = str_start[font_area[f]];
3785 for_end = str_start[font_area[f]+ 1]- 1;
3786 if (k <= for_end) do {
3787 putc(str_pool[k], log_file);
3788 } while(k++ < for_end, stdout);
3789 k = str_start[font_name[f]];
3790 for_end = str_start[font_name[f]+ 1]- 1;
3791 if (k <= for_end) do {
3792 putc(str_pool[k], log_file);
3793 } while(k++ < for_end);
3796 for (k = a+l; k < 16; k++) putc(' ', log_file);
3797 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3798 fputs(buffer, log_file);
3799 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3800 if (suppressname == 0) {
3802 // n = strlen(log_file);
3803 for (k = n; k < 16; k++) putc(' ', log_file);
3804 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3805 font_check[f].b2) << 8 | font_check[f].b3;
3806 decode_fourty(checksum, checksumvector);
3807 fprintf(log_file, "encoding: %s..", checksumvector);
3809 putc('\n', log_file);
3812 /* Allocate table of indeces to allow sorting on font name */
3814 void show_font_info (void)
3816 int k, m, fcount, repeatflag;
3820 for (k = 1; k <= font_ptr; k++)
3821 if (font_used[k])fcount++;
3823 if (fcount == 0) return; /* don't bother to get into trouble */
3825 fnumtable = (short *) malloc (fcount * sizeof(short));
3827 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3829 fprintf(log_file, "\nUsed %d font%s:\n",
3830 fcount, (fcount == 1) ? "" : "s");
3833 for (k = 1; k <= font_ptr; k++)
3834 if (font_used[k])fnumtable[fcount++] = (short) k;
3836 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3839 for (m = 0; m < fcount; m++) {
3841 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3843 else repeatflag = 0;
3845 dvi_font_show(fnumtable[ m], repeatflag);
3848 free((void *)fnumtable);
3851 ////////////////////////////////////////////////////////////////////////////
3853 // Here follows the new stuff for the DLL version
3859 #define SHOWLINEBUFLEN 256
3861 char showlinebuf[SHOWLINEBUFLEN];
3863 // char log_line[MAXLINE];
3865 #define WHITESPACE " \t\n\r"
3867 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3869 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3871 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3872 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3873 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3875 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3877 void ClearShowBuffer (void)
3879 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3880 if (hConsoleWnd != NULL)
3881 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3885 // communicate with DVIWindo (for yandytex.dll)
3887 void show_line (char *line, int errflag) { /* 99/June/11 */
3890 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3891 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3892 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3894 // abort_flag++; // kill job in this case ???
3898 if (showlineinx > 0) ClearShowBuffer();
3900 if (hConsoleWnd != NULL)
3901 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3905 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3906 if (ret == IDCANCEL) {
3908 uexit(1); // dangerous reentry possibility ?
3913 // Provide means for buffering up individual characters
3915 void show_char (int chr) {
3916 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3917 showlinebuf[showlineinx++] = (char) chr;
3918 if (chr == '\n') ClearShowBuffer();
3921 void winshow(char *line) {
3922 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3925 void winerror (char *line) {
3927 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3928 if (ret == IDCANCEL) abort_flag++;
3931 // argument info constructed from command line
3937 // need to be careful here because of quoted args with spaces in them
3938 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3940 int makecommandargs (char *line)
3944 unsigned char *s, *t; // fix 2000 June 18
3946 if (line == NULL) return -1; /* sanity check */
3948 // winerror(line); // debugging only
3950 // s = strtok(line, WHITESPACE);
3951 // while (s != NULL) { /* count arguments */
3953 // s = strtok(NULL, WHITESPACE);
3958 while (*s != '\0') {
3959 while (*s <= 32 && *s > 0) s++;
3960 if (*s == '\0') break;
3962 while (*t > 32 && *t != '\"') t++;
3965 while (*t > 0 && *t != '\"') t++;
3966 if (*t == '\0') break;
3969 // xargv[xargc] = s;
3971 if (*t == '\0') break;
3976 if (xargc == 0) return -1; /* nothing to do */
3978 xargv = (char **) malloc(xargc * sizeof(char *));
3979 if (xargv == NULL) {
3980 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3987 while (*s != '\0') {
3988 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3989 if (*s == '\0') break;
3991 while (*t > ' ' && *t != '\"') t++;
3994 while (*t > 0 && *t != '\"') t++;
3995 if (*t == '\0') break;
3998 // winerror(s); // debugging only
4001 if (*t == '\0') break;
4007 // for (k = 0; k < xargc; k++) { /* create pointers to args */
4008 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
4010 // s += strlen(s) +1;
4016 for (k = 0; k < xargc; k++) {
4017 sprintf(s, "%d\t%s\n", k, xargv[k]);
4025 // refers to TeXAsk in dviwindo.c
4027 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4028 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
4030 // called from tex0.c only --- by initterm and term_input
4032 //int ConsoleInput (char *question, char *buffer)
4033 int ConsoleInput (char *question, char *help, char *buffer)
4037 if (AskUserCall == NULL) return 0;
4038 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4039 // show_line(log_line, 1);
4042 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
4043 // strcpy(buffer, "x");
4044 // strcat(buffer, " "); // ???
4045 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4046 // show_line(log_line, 1);
4047 // input_line_finish(); // ???
4048 // s = buffer + strlen(buffer);
4049 // *s++ = ' '; // space terminate
4050 // *s++ = '\0'; // and null terminate
4051 // returning != 0 means EOF or ^Z
4055 // This is the new entry point of DLL called from DVIWindo
4056 // ARGS: console window to send messages to, command line, callback fun
4057 // no console window output if hConsole is NULL
4058 // returns -1 if it fails --- returns 0 if it succeeds
4060 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4061 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4065 abort_flag = 0; // redundant
4066 hConsoleWnd = NULL; // redundant
4068 AskUserCall = AskUser; // remember callback
4070 hConsoleWnd = hConsole; // remember console window handle
4072 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4073 // if (grabenv("DEBUGPAUSE") != NULL) {
4074 // show_line(line, 0); // debugging - show command line
4075 // show_line("\n", 0);
4078 xargc = makecommandargs(line); // sets up global *xargv[]
4080 if (xargc < 0) return -1; // sanity check
4082 if (hConsoleWnd != NULL)
4083 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4084 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4087 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
4089 if (err_level > 0 || abort_flag > 0) {
4090 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4091 // err_level, abort_flag);
4092 // winerror(log_line);
4095 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
4096 // if (psbufpos > 0) PSputs("", output); // output already closed
4098 if (hConsoleWnd != NULL) {
4099 if (err_level > 0 || abort_flag > 0) flag = 1;
4100 else flag = 0; // pass along error indication
4101 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
4103 // PScallback = NULL;
4106 if (xargv != NULL) free(xargv);
4107 if (abort_flag) return -1;
4111 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4114 switch (fdwReason) {
4115 case DLL_PROCESS_ATTACH:
4116 // The DLL is being mapped into the process's address space
4117 // place to allocate memory ???
4118 // return FALSE if this fails
4119 hInstanceDLL = hInstDll; /* remember it */
4122 case DLL_THREAD_ATTACH:
4123 // A thread is being created
4126 case DLL_THREAD_DETACH:
4127 // A thread is exiting cleanly
4130 case DLL_PROCESS_DETACH:
4131 // The DLL is being unmapped from the process's address space
4132 // place to free any memory allocated
4133 // but make sure it in fact *was* allocated
4134 hInstanceDLL = NULL; /* forget it */
4137 return(TRUE); // used only for DLL_PROCESS_ATTACH
4139 #endif // end of new stuff for DLL version
4141 //////////////////////////////////////////////////////////////////////////////
4145 /* NOTE: current_tfm = false (-c)
4146 not checking for TFM in current directory saves 0.1 sec
4147 (0.2 if file_method = false (-G) */
4149 /* NOTE: test_dir_access = false (-b):
4150 not checking whether readable file is a directory saves maybe 0.5 sec
4151 BUT only if file_method = false (-G) - otherwise its irrelevant */
4153 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4154 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4155 BUT not if current_tfm = false (-c) */
4157 /* NOTE: file_method = false (-G) --- method for checking file accessible
4158 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4160 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4162 /* constants for _heapchk/_heapset/_heapwalk routines */
4163 /* #define _HEAPEMPTY (-1) */
4164 /* #define _HEAPOK (-2) */
4165 /* #define _HEAPBADBEGIN (-3) */
4166 /* #define _HEAPBADNODE (-4) */
4167 /* #define _HEAPEND (-5) */
4168 /* #define _HEAPBADPTR (-6) */
4170 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4172 /* buffercopy no longer used */
4174 /* To Knuthian reset right when command line interpreted */