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)
504 /* double x = 1.0; */
505 /* double dx = DBL_EPSILON; */
509 /* while (x + dx != 1.0) { */
510 while (1.0 + dx != 1.0)
516 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
517 show_line(log_line, 0);
521 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
523 char *debugfile; /* NULL or name of file to try and open */
526 char *heapstrings[] =
528 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
532 /* Attempt to get at problem with eqtb ... temporarily abandoned */
534 void check_eqtb (char *act)
537 memory_word *eqtb = zeqtb;
538 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
539 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
540 if (eqtb[k].cint != 0) {
543 show_line("EQTB ", 0);
545 sprintf(log_line, "%d ", k);
546 show_line(log_line, 0);
547 if (count++ > 256) break;
550 if (count != 0) show_char('\n');
554 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
558 /* ad hoc default minimum growth in memory realloc is 62% */
559 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
560 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
561 int total_allocated = 0; /* total memory allocated so far */
562 int ini_max_address = 0; /* maximum address when starting */
563 int max_address = 0; /* maximum address seen in allocated memory */
567 // DON'T USE THIS in DLL VERSION
571 unsigned int heapthreshold=0; /* smallest size block interested in ... */
573 unsigned int heap_dump (FILE *output, int verbose)
575 unsigned int total=0;
576 struct _heapinfo hinfo;
581 if (verbose) fprintf(output, "HEAP DUMP:\n");
583 /* if ((n = _heapchk ()) != _HEAPOK) { */
590 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
592 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
595 hinfo._pentry = NULL;
596 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
597 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
598 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
600 end_block = (int) hinfo._pentry + hinfo._size;
601 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
602 if (hinfo._size >= heapthreshold && verbose)
603 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
604 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
605 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
608 switch (heapstatus) {
610 if (verbose) fprintf(output, "OK - empty heap\n");
613 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
616 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
619 fprintf(output, "ERROR - %s\n", "bad start of heap");
622 fprintf(output, "ERROR - %s\n", "bad node in heap");
630 void show_maximums (FILE *output)
633 unsigned heaptotal=0; /* no longer used */
634 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
636 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
637 // if (output != NULL) fputs(log_line, output); // log file
638 // else if (flag == 0) show_line(log_line, 0); // informative
639 // else if (flag == 1) show_line(log_line, 1); // error
640 if (output == stderr) show_line(log_line, 1);
641 else if (output == stdout) show_line(log_line, 0);
642 else fputs(log_line, output);
645 /* our own version of realloc --- avoid supposed MicroSoft version bug */
646 /* also tries _expand first, which can avoid address growth ... */
649 void *ourrealloc (void *old, size_t new_size)
652 size_t old_size, overlap;
654 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
655 if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
657 if (old == NULL) return malloc (new_size); /* no old block - use malloc */
659 old_size = _msize (old);
660 if (old_size >= new_size && old_size < new_size + 4) return old;
661 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
664 show_line("BEFORE REALLOC: \n", 0);
666 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
670 mnew = _expand (old, new_size); /* first try and expand in place */
673 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
674 mnew, new_size, old, old_size);
675 show_line(log_line, 0);
679 /* *********************************************************************** */
680 /* do this if you want to call the real realloc next - */
681 mnew = realloc (old, new_size);
684 show_line("AFTER REALLOC: \n", 0);
686 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
690 if (mnew != NULL) return mnew;
691 /* we are screwed typically if we ever drop through here - no more space */
692 /* *********************************************************************** */
693 mnew = malloc (new_size); /* otherwise find new space */
694 if (mnew == NULL) return mnew; /* if unable to allocate */
695 if (old_size < new_size) overlap = old_size;
696 else overlap = new_size;
697 memcpy (mnew, old, overlap); /* copy old data to new area */
698 free(old); /* free the old area */
703 void memory_error (char *s, int n)
706 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
707 show_maximums(log_file);
709 if (heap_flag) (void) heap_dump(log_file, 1);
712 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
713 show_line(log_line, 1);
714 show_maximums(stderr);
716 if (heap_flag) (void) heap_dump(stderr, 1);
718 /* exit (1); */ /* 94/Jan/22 */
719 /* return to let TeX do its thing (such as complain about runaway) */
720 /* don't set abort_flag here */
723 void trace_memory (char *s, int n)
725 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
726 show_line(log_line, 0);
729 void update_statistics (int address, int size, int oldsize)
731 if (address + size > max_address) max_address = address + size;
732 total_allocated = total_allocated + size - oldsize;
735 void probe_memory (void)
738 s = (char *) malloc (4); /* get current top address */
740 update_statistics ((int) s, 0, 0); /* show where we are */
743 void probe_show (void)
746 show_maximums(stdout);
748 if (heap_flag) (void) heap_dump(stdout, 1);
752 size_t roundup (size_t n)
754 if ((n % 4) == 0) return n;
755 else return ((n / 4) + 1) * 4;
759 /* using allocating hyphenation trie slows things down maybe 1% */
760 /* but saves typically (270k - 55k) = 215k of memory */
761 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
762 /* since hyphenation trie cannot be extended (after iniTeX) */
763 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
765 /* NOTE: we don't ever reallocate these */
766 /* returns -1 if it fails */
768 int allocate_tries (int trie_max)
771 /* if (trie_max > trie_size) {
772 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
773 trie_max, trie_size);
774 show_line(log_line, 1);
776 } */ /* ??? removed 1993/dec/17 */
777 if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
778 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
779 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
780 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
781 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
783 if (trace_flag) trace_memory("hyphen trie", n);
784 trie_trl = (halfword *) malloc (roundup(nl));
785 trie_tro = (halfword *) malloc (roundup(no));
786 trie_trc = (quarterword *) malloc (roundup(nc));
787 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
789 memory_error("hyphen trie", n);
794 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
795 show_line(log_line, 0);
797 update_statistics ((int) trie_trl, nl, 0);
798 update_statistics ((int) trie_tro, no, 0);
799 update_statistics ((int) trie_trc, nc, 0);
800 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
801 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
803 probe_show(); /* 94/Mar/25 */
808 #ifdef ALLOCATEHYPHEN
809 bool prime (int); /* test function later in this file */
811 int current_prime = 0; /* remember in case reallocated later */
813 /* we don't return an address here, since TWO memory regions allocated */
814 /* plus, we don't really reallocate, we FLUSH the old information totally */
815 /* returns -1 if it fails */
817 int realloc_hyphen (int hyphen_prime)
821 if (!prime(hyphen_prime))
823 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
824 show_line(log_line, 1);
828 /* need not/cannot preserve old contents when hyphen prime is changed */
829 /* if (hyph_list != NULL) free(hyph_list); */
830 /* if (hyph_word != NULL) free(hyph_word); */
831 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
832 nw = (hyphen_prime + 1) * sizeof(str_number);
833 nl = (hyphen_prime + 1) * sizeof(halfword);
835 if (trace_flag) trace_memory("hyphen exception", n);
836 /* initially hyph_word will be NULL so this acts like malloc */
837 /* hyph_word = (str_number *) malloc (nw); */
838 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
839 /* initially hyph_list will be NULL so this acts like malloc */
840 /* hyph_list = (halfword *) malloc (nl); */
841 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
843 if (hyph_word == NULL || hyph_list == NULL)
845 memory_error("hyphen exception", n);
850 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
851 show_line(log_line, 0);
853 /* cannot preserve old contents when hyphen prime is changed */
855 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
857 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
860 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
862 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
864 hyph_count = 0; /* or use reset_hyphen() in itex.c */
865 if (current_prime != 0)
867 update_statistics ((int) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
868 update_statistics ((int) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
872 update_statistics ((int) hyph_word, nw, 0);
873 update_statistics ((int) hyph_list, nl, 0);
875 current_prime = hyphen_prime;
876 if (trace_flag) probe_show(); /* 94/Mar/25 */
881 int current_mem_size=0; /* current total words in main mem allocated -1 */
883 /* this gets called from itex.c when it figures out what mem_top is */
884 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
885 /* initial allocation only, may get expanded later */
886 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
887 /* returns NULL if it fails */
890 /* initial main memory alloc - mem_top */
891 memory_word *allocate_main_memory (int size)
895 /* Using -i *and* pre-loading format */ /* in this case get called twice */
896 /* Get rid of initial blank memory again or use realloc ... */
897 /* Could we avoid this by detecting presence of & before allocating ? */
898 /* Also, if its already large enough, maybe we can avoid this ? */
899 /* don't bother if current_mem_size == mem_max - mem_start ? */
900 if (mainmemory != NULL)
902 /* free(mainmemory); */
903 /* mainmemory = NULL; */
904 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
905 /* if (mem_spec_flag)
906 show_line("Cannot change initial main memory size when format is read\n", 1);*/
909 mem_top = mem_bot + size;
910 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
911 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
914 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
915 if (mem_extra_low != 0 && !is_initex)
916 mem_start = mem_bot - mem_extra_low; /* increase main memory */
918 mem_start = 0; /* bottom of memory allocated by system */
919 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
920 mem_min = 0; /* bottom of area made available to TeX */
921 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
922 if (trace_flag) trace_memory("main memory", n);
923 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
924 /* normally mainmemory == NULL here so acts like malloc ... */
925 mainmemory = (memory_word *) REALLOC (mainmemory, n);
926 if (mainmemory == NULL) {
927 memory_error("initial main memory", n);
928 // exit (1); /* serious error */
932 sprintf(log_line, "Address main memory == %d\n", mainmemory);
933 show_line(log_line, 0);
936 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
938 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
939 show_line(log_line, 0);
941 update_statistics ((int) mainmemory, n,
942 (current_mem_size + 1) * sizeof (memory_word));
943 /* current_mem_size = (mem_max - mem_start + 1); */
944 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
945 if (trace_flag) probe_show(); /* 94/Mar/25 */
946 return zzzaa; /* same as zmem, mem 94/Jan/24 */
948 #endif /* end of ALLOCATEMAIN */
951 /* int firstallocation = 1; */
953 /* increase main memory allocation at low end and high end */
954 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
955 /* returns NULL if it fails */
957 memory_word *realloc_main (int losize, int hisize)
960 int newsize = 0; /* to quieten compiler */
961 int n = 0; /* to quieten compiler */
962 memory_word * newmemory = NULL; /* to quieten compiler */
964 /* if (losize == 0 && hisize > 0) runawayflag = 1;
965 else runawayflag = 0; */ /* 94/Jan/22 */
968 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
969 show_line(log_line, 0);
972 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
974 show_line("Please use `-m=...' on command line\n", 0);
975 // abort_flag++; // ???
979 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
980 show_line(log_line, 0);
982 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
983 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
984 // abort_flag++; // ???
987 /* first allocation should expand *both* lo and hi */
988 if (hisize == 0 && mem_end == mem_max) hisize = losize;
989 if (losize == 0 && mem_start == mem_min) losize = hisize;
990 /* try and prevent excessive frequent reallocations */
991 /* while avoiding over allocation by too much */
992 minsize = current_mem_size / 100 * percent_grow;
993 if (losize + hisize < minsize) {
994 if (losize > 0 && hisize > 0) {
995 losize = minsize / 2;
996 hisize = minsize / 2;
998 else if (losize > 0) losize = minsize;
999 else if (hisize > 0) hisize = minsize;
1001 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
1002 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
1004 for (k = 0; k < MAXSPLITS; k++) {
1005 newsize = current_mem_size + losize + hisize;
1006 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
1007 while (newsize >= max_mem_size) {
1008 losize = losize / 2; hisize = hisize / 2;
1009 newsize = current_mem_size + losize + hisize;
1012 n = (newsize + 1) * sizeof (memory_word);
1013 if (trace_flag) trace_memory("main memory", n);
1014 newmemory = (memory_word *) REALLOC (mainmemory, n);
1015 if (newmemory != NULL) break; /* did we get it ? */
1016 if (current_mem_size == 0) break; /* in case we ever use for initial */
1017 losize = losize / 2; hisize = hisize / 2;
1020 if (newmemory == NULL) {
1021 memory_error("main memory", n);
1022 return zzzaa; /* try and continue with TeX !!! */
1025 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1026 show_line(log_line, 0);
1029 /* shift everything upward to make space for new low area */
1031 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1032 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1033 show_line(log_line, 0);
1035 memmove (newmemory + losize, newmemory,
1036 /* current_mem_size * sizeof(memory_word)); */
1037 (current_mem_size + 1) * sizeof(memory_word));
1038 /* could reduce words moved by (mem_max - mem_end) */
1040 mainmemory = newmemory; /* remember for free later */
1041 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1042 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1043 update_statistics ((int) mainmemory, n,
1044 (current_mem_size + 1) * sizeof (memory_word));
1045 current_mem_size = newsize;
1046 if (current_mem_size != mem_max - mem_start) {
1047 show_line("ERROR: Impossible Memory Error\n", 1);
1049 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1050 else zzzaa = mainmemory;
1051 if (trace_flag) probe_show(); /* 94/Mar/25 */
1057 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1059 int current_font_mem_size=0;
1061 /* fmemoryword can be either halfword or memory_word */
1062 fmemoryword *realloc_font_info (int size)
1063 { /* number of memorywords */
1064 fmemoryword *newfontinfo=NULL;
1066 int newsize=0; /* to quieten compiler */
1067 int n=0; /* to quieten compiler */
1070 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1071 show_line(log_line, 0);
1073 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1074 /* during initial allocation current_font_mem_size == 0 */
1075 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1076 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1077 return font_info; /* pass it back to TeX 99/Fabe/4 */
1079 /* try and prevent excessive frequent reallocations */
1080 /* while avoiding over allocation by too much */
1081 /* minsize = current_font_mem_size / 2; */
1082 minsize = current_font_mem_size / 100 * percent_grow;
1083 if (size < minsize) size = minsize;
1084 if (size < initial_font_mem_size) size = initial_font_mem_size;
1086 for (k=0; k < MAXSPLITS; k++) {
1087 newsize = current_font_mem_size + size;
1088 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1089 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1090 n = (newsize + 1) * sizeof (fmemoryword);
1091 if (trace_flag) trace_memory("font_info", n);
1092 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1093 if (newfontinfo != NULL) break; /* did we get it ? */
1094 if (current_font_mem_size == 0) break; /* initial allocation must work */
1098 if (newfontinfo == NULL) {
1099 memory_error("font", n);
1100 return font_info; /* try and continue !!! */
1102 font_info = newfontinfo;
1104 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1105 show_line(log_line, 0);
1107 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1108 current_font_mem_size = newsize;
1109 if (trace_flag) probe_show(); /* 94/Mar/25 */
1114 #ifdef ALLOCATESTRING
1115 int current_pool_size=0;
1117 packed_ASCII_code *realloc_str_pool (int size)
1122 packed_ASCII_code *newstrpool=NULL;
1125 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1126 show_line(log_line, 0);
1128 if (current_pool_size == pool_size) {
1129 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1131 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1133 /* minsize = current_pool_size / 2; */
1134 minsize = current_pool_size / 100 * percent_grow;
1135 if (size < minsize) size = minsize;
1136 if (size < initial_pool_size) size = initial_pool_size;
1138 for (k = 0; k < MAXSPLITS; k++) {
1139 newsize = current_pool_size + size;
1140 if (newsize > pool_size) newsize = pool_size;
1141 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1142 n = (newsize + 1) * sizeof (packed_ASCII_code);
1143 if (trace_flag) trace_memory("str_pool", n);
1144 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1145 if (newstrpool != NULL) break; /* did we get it ? */
1146 if (current_pool_size == 0) break; /* initial allocation must work */
1147 size = size / 2; /* else can retry smaller */
1150 if (newstrpool == NULL) {
1151 memory_error("string pool", n);
1152 return str_pool; /* try and continue !!! */
1154 str_pool = newstrpool;
1155 update_statistics ((int) str_pool, n, current_pool_size);
1156 current_pool_size = newsize;
1158 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1159 show_line(log_line, 0);
1161 if (trace_flag) probe_show(); /* 94/Mar/25 */
1166 #ifdef ALLOCATESTRING
1167 int current_max_strings=0;
1169 pool_pointer *realloc_str_start (int size)
1174 pool_pointer *newstrstart=NULL;
1177 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1178 show_line(log_line, 0);
1180 if (current_max_strings == max_strings) {
1181 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1183 return str_start; /* pass it back to TeX 99/Fabe/4 */
1185 /* minsize = current_max_strings / 2; */
1186 minsize = current_max_strings / 100 * percent_grow;
1187 if (size < minsize) size = minsize;
1188 if (size < initial_max_strings) size = initial_max_strings;
1190 for (k = 0; k < MAXSPLITS; k++) {
1191 newsize = current_max_strings + size;
1192 if (newsize > max_strings) newsize = max_strings;
1193 /* important + 1 since str_start[maxstring + 1] originally */
1194 n = (newsize + 1) * sizeof (pool_pointer);
1195 if (trace_flag) trace_memory("str_start", n);
1196 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1197 if (newstrstart != NULL) break; /* did we get it ? */
1198 if (current_max_strings == 0) break; /* initial allocation must work */
1199 size = size / 2; /* otherwise can try smaller */
1202 if (newstrstart == NULL) {
1203 memory_error("string pointer", n);
1204 return str_start; /* try and continue */
1206 str_start = newstrstart;
1207 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1208 current_max_strings = newsize;
1210 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1211 show_line(log_line, 0);
1213 if (trace_flag) probe_show(); /* 94/Mar/25 */
1220 /* returns -1 if it fails */
1222 int allocate_ini (int size)
1223 { /* size == trie_size */
1224 int n, nl, no, nc, nr, nh, nt;
1225 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1226 no = (size + 1) * sizeof(trie_op_code);
1227 nc = (size + 1) * sizeof(packed_ASCII_code);
1228 /* nt = (size + 1) * sizeof(bool); */
1229 nt = (size + 1) * sizeof(char);
1230 n = nl + no + nc + nr + nh + nt;
1231 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1232 3 * sizeof(trie_pointer) + sizeof (char)); */
1233 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1234 trie_l = (trie_pointer *) malloc (roundup(nl));
1235 trie_o = (trie_op_code *) malloc (roundup(no));
1236 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1237 trie_r = (trie_pointer *) malloc (roundup(nr));
1238 trie_hash = (trie_pointer *) malloc (roundup(nh));
1239 /* trie_taken = (bool *) malloc (nt); */
1240 trie_taken = (char *) malloc (roundup(nt));
1241 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1242 trie_hash == NULL || trie_taken == NULL) {
1243 memory_error("iniTeX hyphen trie", n);
1244 // exit (1); /* serious error */
1248 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1249 trie_l, trie_o, trie_c);
1250 show_line(log_line, 0);
1251 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1252 trie_r, trie_hash, trie_taken);
1253 show_line(log_line, 0);
1255 update_statistics ((int) trie_l, nl, 0);
1256 update_statistics ((int) trie_o, no, 0);
1257 update_statistics ((int) trie_c, nc, 0);
1258 update_statistics ((int) trie_r, nr, 0);
1259 update_statistics ((int) trie_hash, nh, 0);
1260 update_statistics ((int) trie_taken, nt, 0);
1261 /* trie_size = size; */ /* ??? */
1262 if (trace_flag) probe_show(); /* 94/Mar/25 */
1263 return 0; // success
1267 #ifdef ALLOCATESAVESTACK
1268 int current_save_size=0;
1270 memory_word *realloc_save_stack (int size)
1274 memory_word *newsave_stack=NULL;
1277 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1278 show_line(log_line, 0);
1280 if (current_save_size == save_size) { /* arbitrary limit */
1281 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1283 return save_stack; /* let TeX handle the error */
1285 minsize = current_save_size / 100 * percent_grow;
1286 if (size < minsize) size = minsize;
1287 if (size < initial_save_size) size = initial_save_size;
1289 for (k = 0; k < MAXSPLITS; k++) {
1290 newsize = current_save_size + size;
1291 if (newsize > save_size) newsize = save_size;
1292 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1293 if (trace_flag) trace_memory("save_stack", n);
1294 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1295 if (newsave_stack != NULL) break; /* did we get it ? */
1296 if (current_save_size == 0) break; /* initial allocation must work */
1297 size = size / 2; /* else can retry smaller */
1300 if (newsave_stack == NULL) {
1301 memory_error("save stack", n);
1302 return save_stack; /* try and continue !!! */
1304 save_stack = newsave_stack;
1305 update_statistics ((int) save_stack, n, current_save_size);
1306 current_save_size = newsize;
1308 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1309 show_line(log_line, 0);
1310 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1311 show_line(log_line, 0);
1313 if (trace_flag) probe_show(); /* 94/Mar/25 */
1318 #ifdef ALLOCATEINPUTSTACK
1319 int current_stack_size=0; /* input stack size */
1321 in_state_record *realloc_input_stack (int size)
1325 in_state_record *newinputstack=NULL;
1328 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1329 show_line(log_line, 0);
1331 if (current_stack_size == stack_size) { /* arbitrary limit */
1332 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1336 minsize = current_stack_size / 100 * percent_grow;
1337 if (size < minsize) size = minsize;
1338 if (size < initial_stack_size) size = initial_stack_size;
1340 for (k = 0; k < MAXSPLITS; k++) {
1341 newsize = current_stack_size + size;
1342 if (newsize > stack_size) newsize = stack_size;
1343 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1344 if (trace_flag) trace_memory("input_stack", n);
1345 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1346 if (newinputstack != NULL) break; /* did we get it ? */
1347 if (current_stack_size == 0) break; /* initial allocation must work */
1348 size = size / 2; /* else can retry smaller */
1351 if (newinputstack == NULL) {
1352 memory_error("input stack", n);
1353 return input_stack; /* try and continue !!! */
1355 input_stack = newinputstack;
1356 update_statistics ((int) input_stack, n, current_stack_size);
1357 current_stack_size = newsize;
1359 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1360 show_line(log_line, 0);
1361 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1362 show_line(log_line, 0);
1364 if (trace_flag) probe_show(); /* 94/Mar/25 */
1369 #ifdef ALLOCATENESTSTACK
1370 int current_nest_size=0; /* current nest size */
1372 list_state_record *realloc_nest_stack (int size)
1376 list_state_record *newnest=NULL;
1379 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1380 show_line(log_line, 0);
1382 if (current_nest_size == nest_size) { /* arbitrary limit */
1383 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1385 return nest; /* let TeX handle the error */
1387 minsize = current_nest_size / 100 * percent_grow;
1388 if (size < minsize) size = minsize;
1389 if (size < initial_nest_size) size = initial_nest_size;
1391 for (k = 0; k < MAXSPLITS; k++) {
1392 newsize = current_nest_size + size;
1393 if (newsize > nest_size) newsize = nest_size;
1394 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1395 if (trace_flag) trace_memory("nest stack", n);
1396 newnest = (list_state_record *) REALLOC (nest, n);
1397 if (newnest != NULL) break; /* did we get it ? */
1398 if (current_nest_size == 0) break; /* initial allocation must work */
1399 size = size / 2; /* else can retry smaller */
1402 if (newnest == NULL) {
1403 memory_error("nest stack", n);
1404 return nest; /* try and continue !!! */
1407 update_statistics ((int) nest, n, current_nest_size);
1408 current_nest_size = newsize;
1410 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1411 show_line(log_line, 0);
1412 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1413 show_line(log_line, 0);
1415 if (trace_flag) probe_show(); /* 94/Mar/25 */
1420 #ifdef ALLOCATEPARAMSTACK
1421 int current_param_size=0; /* current param size */
1423 halfword *realloc_param_stack (int size)
1427 halfword *newparam=NULL;
1430 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1431 show_line(log_line, 0);
1433 if (current_param_size == param_size) { /* arbitrary limit */
1434 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1436 return param_stack; /* let TeX handle the error */
1438 minsize = current_param_size / 100 * percent_grow;
1439 if (size < minsize) size = minsize;
1440 if (size < initial_param_size) size = initial_param_size;
1442 for (k = 0; k < MAXSPLITS; k++) {
1443 newsize = current_param_size + size;
1444 if (newsize > param_size) newsize = param_size;
1445 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1446 if (trace_flag) trace_memory("param stack", n);
1447 newparam = (halfword *) REALLOC (param_stack, n);
1448 if (newparam != NULL) break; /* did we get it ? */
1449 if (current_param_size == 0) break; /* initial allocation must work */
1450 size = size / 2; /* else can retry smaller */
1453 if (newparam == NULL) {
1454 memory_error("param stack", n);
1455 return param_stack; /* try and continue !!! */
1457 param_stack = newparam;
1458 update_statistics ((int) param_stack, n, current_param_size);
1459 current_param_size = newsize;
1461 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1462 show_line(log_line, 0);
1463 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1464 show_line(log_line, 0);
1466 if (trace_flag) probe_show(); /* 94/Mar/25 */
1471 #ifdef ALLOCATEBUFFER
1472 int current_buf_size=0;
1474 ASCII_code *realloc_buffer (int size)
1478 ASCII_code *newbuffer=NULL;
1481 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1482 show_line(log_line, 0);
1484 if (current_buf_size == buf_size) { /* arbitrary limit */
1485 /* memory_error ("buffer", buf_size); */
1487 return buffer; /* pass it back to TeX 99/Fabe/4 */
1489 minsize = current_buf_size / 100 * percent_grow;
1490 if (size < minsize) size = minsize;
1491 if (size < initial_buf_size) size = initial_buf_size;
1493 for (k = 0; k < MAXSPLITS; k++) {
1494 newsize = current_buf_size + size;
1495 if (newsize > buf_size) newsize = buf_size;
1496 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1497 if (trace_flag) trace_memory("buffer", n);
1498 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1499 if (newbuffer != NULL) break; /* did we get it ? */
1500 if (current_buf_size == 0) break; /* initial allocation must work */
1501 size = size / 2; /* else can retry smaller */
1504 if (newbuffer == NULL) {
1505 memory_error("buffer", n);
1506 return buffer; /* try and continue !!! */
1509 update_statistics ((int) buffer, n, current_buf_size);
1511 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1513 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1515 current_buf_size = newsize;
1517 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1518 show_line(log_line, 0);
1519 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1520 show_line(log_line, 0);
1522 if (trace_flag) probe_show(); /* 94/Mar/25 */
1527 /* we used to allocate this one only to reduce the size of the PE file */
1528 /* not used anymore - NO advantage */
1530 #ifdef ALLOCATEDVIBUF
1531 eight_bits *allocatedvibuf (int size)
1533 eight_bits *dvi_buf;
1536 n = (size + 1) * sizeof(eight_bits);
1537 if (trace_flag) trace_memory("dvi_buf", n);
1538 dvi_buf = (eight_bits *) malloc (roundup(n));
1539 if (dvi_buf == NULL) {
1540 memory_error("dvi_buf", n);
1544 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1545 show_line(log_line, 0);
1547 update_statistics ((int) dvi_buf, n, 0);
1548 if (trace_flag) probe_show(); /* 94/Mar/25 */
1553 /* we used to allocate this one only to reduce the size of the PE file */
1554 /* it can be done without loss in performance, since register eqtb = zeqtb */
1555 #ifdef ALLOCATEZEQTB
1556 memory_word *allocatezeqtb (int k)
1561 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1562 if (trace_flag) trace_memory("eqtb", n);
1563 zeqtb = (memory_word *) malloc (roundup(n));
1564 if (zeqtb == NULL) {
1565 memory_error("eqtb", n);
1566 // exit (1); /* serious error */
1570 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1571 show_line(log_line, 0);
1573 update_statistics ((int) zeqtb, n, 0);
1574 if (trace_flag) probe_show(); /* 94/Mar/25 */
1579 /* here is the main memory allocation routine -- calls the above */
1580 /* returns -1 if it fails */
1581 /* allocate rather than static 93/Nov/26 */
1582 int allocate_memory (void)
1586 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1590 #error ERROR: Not ready for ALLOCATEHASH...
1593 /* probably not worth while/not a good idea allocating following */
1594 /* they are all rather small, and typically don't need expansion */
1595 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1597 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1598 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1599 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1601 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1602 zzzae = (htwohalves *) malloc (roundup(n));
1604 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1605 zzzae = (twohalves *) malloc (roundup(n));
1607 if (trace_flag) trace_memory("hash table", n);
1608 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1611 memory_error("hash table", n);
1612 // exit (1); /* serious error */
1613 return -1; /* serious error */
1616 n = (inputsize + 1) * sizeof(memory_word);
1617 if (trace_flag) trace_memory("input_stack", n);
1618 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1619 input_stack = (memory_word *) malloc (roundup(n));
1620 if (input_stack == NULL) {
1621 memory_error("input_stack", n);
1622 // exit (1); /* serious error */
1623 return -1; /* serious error */
1627 /* no real reason to allocate dvi_buf - no need to ever grow it */
1628 #ifdef ALLOCATEDVIBUF
1629 /* zdvibuf = NULL; */
1630 zdvibuf = allocatedvibuf (dvi_buf_size);
1631 if (zdvibuf == NULL) return -1;
1634 #ifdef ALLOCATEZEQTB
1636 #ifdef INCREASEFONTS
1637 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1638 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1640 /* zeqtb = allocatezeqtb (13507); */
1641 zeqtb = allocatezeqtb (hash_size + 4007);
1645 #ifdef ALLOCATEINPUTSTACK
1646 input_stack = NULL; /* new 1999/Jan/21 */
1647 current_stack_size = 0;
1648 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1651 #ifdef ALLOCATENESTSTACK
1652 nest = NULL; /* new 1999/Jan/21 */
1653 current_nest_size = 0;
1654 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1657 #ifdef ALLOCATEPARAMSTACK
1658 param_stack = NULL; /* new 1999/Jan/21 */
1659 current_param_size = 0;
1660 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1663 #ifdef ALLOCATESAVESTACK
1664 save_stack = NULL; /* new 1999/Jan/7 */
1665 current_save_size = 0;
1666 save_stack = realloc_save_stack (initial_save_size);
1670 buffer = NULL; /* need to do earlier */
1671 current_buf_size = 0;
1672 buffer = realloc_buffer (initial_buf_size);
1675 #ifdef ALLOCATESTRING
1677 current_pool_size = 0;
1679 current_max_strings = 0;
1680 /* need to create space because iniTeX writes in before reading pool file */
1681 /* for a start, puts in strings for 256 characters */
1682 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1684 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1685 str_pool = realloc_str_pool (initial_pool_size);
1686 str_start = realloc_str_start (initial_max_strings);
1690 /* the following can save a lot of the usual 800k fixed allocation */
1693 current_font_mem_size = 0;
1694 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1695 /* if ini-TeX we need to do it here - no format file read later */
1696 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1702 mem_min = mem_bot; /* just to avoid complaints in texbody */
1703 mem_top = mem_initex;
1705 /* allocate main memory here if this is iniTeX */
1706 /* otherwise wait for format undumping in itex.c ... */
1708 /* avoid this if format specified on command line ??? */
1709 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1710 mem = allocate_main_memory(mem_initex); /* made variable ! */
1713 return -1; /* serious error */
1717 /* now for the hyphenation exception stuff */
1718 #ifdef ALLOCATEHYPHEN
1721 /* this will be overridden later by what is in format file */
1722 hyphen_prime = default_hyphen_prime;
1723 /* non ini-TeX use assumes format will be read and that specifies size */
1726 if (new_hyphen_prime)
1727 hyphen_prime = new_hyphen_prime;
1728 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1733 /* now for memory for the part of the hyphenation stuff that always needed */
1734 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1735 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1736 #ifdef ALLOCATETRIES
1739 if (allocate_tries (trie_size))
1744 /* now for memory for hyphenation stuff needed only when running iniTeX */
1748 if (allocate_ini(trie_size))
1753 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1754 trie_c = NULL; /* (trie_size + 1) * char */
1755 trie_taken = NULL; /* (trie_size + 1) * bool */
1759 free(holeadr); /* create the hole */
1761 return 0; // success
1764 /* returns non-zero if error - done to test integrity of stack mostly */
1765 /* free in reverse order 93/Nov/26 */
1766 int free_memory (void)
1769 unsigned heaptotal=0;
1770 /* unsigned total; */
1772 if (trace_flag) show_line("free_memory ", 0);
1775 if (debug_flag) check_eqtb("free_memory");
1777 if (verbose_flag || trace_flag) show_maximums(stdout);
1779 if (heap_flag) (void) heap_dump(stdout, 1);
1783 heaptotal = (void) heap_dump(stdout, 0);
1785 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1786 heaptotal, max_address);
1787 show_line(log_line, 0);
1790 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1791 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1792 show_line(log_line, 0);
1794 /* following only needed to check consistency of heap ... useful debugging */
1795 if (trace_flag) show_line("Freeing memory again\n", 0);
1798 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1800 /* the following checks the heap integrity */
1802 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1804 #ifdef SHOWHEAPERROR
1806 if (n != _HEAPOK) { /* 94/Feb/18 */
1807 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1808 show_line(log_line, 1);
1809 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1810 show_line(log_line, 0);
1811 return n; /* non-zero and negative */ /* unreachable ??? */
1814 /* only free memory if safe ... additional check */
1817 if (trie_taken != NULL) free(trie_taken);
1818 if (trie_hash != NULL) free(trie_hash);
1819 if (trie_r != NULL) free(trie_r);
1820 if (trie_c != NULL) free(trie_c);
1821 if (trie_o != NULL) free(trie_o);
1822 if (trie_l != NULL) free(trie_l);
1824 trie_hash = trie_l = trie_r = NULL;
1829 #ifdef ALLOCATETRIES
1830 if (trie_trc != NULL) free (trie_trc);
1831 if (trie_tro != NULL) free (trie_tro);
1832 if (trie_trl != NULL) free (trie_trl);
1834 trie_tro = trie_trl = NULL;
1836 #ifdef ALLOCATEHYPHEN
1837 if (hyph_list != NULL) free(hyph_list);
1838 if (hyph_word != NULL) free(hyph_word);
1843 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1844 if (mainmemory != NULL) free(mainmemory);
1848 if (font_info != NULL) free(font_info);
1851 #ifdef ALLOCATESTRING
1852 if (str_start != NULL) free(str_start);
1853 if (str_pool != NULL) free(str_pool);
1859 if (zzzae != NULL) free(zzzae);
1863 #ifdef ALLOCATEDVIBUF
1864 if (zdvibuf != NULL) free(zdvibuf);
1867 #ifdef ALLOCATEZEQTB
1868 if (zeqtb != NULL) free(zeqtb);
1872 #ifdef ALLOCATEPARAMSTACK
1873 if (param_stack != NULL) free(param_stack);
1876 #ifdef ALLOCATENESTSTACK
1877 if (nest != NULL) free(nest);
1880 #ifdef ALLOCATEINPUTSTACK
1881 if (input_stack != NULL) free(input_stack);
1884 #ifdef ALLOCATESAVESTACK
1885 if (save_stack != NULL) free(save_stack);
1888 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1889 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1890 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1891 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1892 format_file = string_file = source_direct = NULL;
1893 if (dvi_file_name != NULL) free(dvi_file_name);
1894 if (log_file_name != NULL) free(log_file_name);
1895 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1902 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1903 if (x % 2 == 0) return false;
1904 for (k = 3; k < x; k = k + 2) {
1905 if (x % k == 0) return false;
1906 /* if (k * k > x) return true; */
1907 if (sum * 4 > x) return true;
1914 bool show_use=false;
1915 bool floating=false;
1917 void complainarg (int c, char *s)
1919 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1920 show_line(log_line, 1);
1921 show_use = 1; // 2000 June 21
1924 /* following is list of allowed command line flags and args */
1926 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1928 /* only 01234567.9 still left to take ... maybe recycle u */
1930 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1932 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1934 void reorderargs (int ac, char **av)
1935 { /* put in 1993/Dec/28 */
1938 // char takeargs[128]; /* large enough for all command line arg chars */
1939 char takeargs[256]; /* large enough for all command line arg chars */
1941 /* assumes arg pointers av[] are writeable */
1942 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1944 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1945 /* show_line("No arguments?\n", 0); */ /* debugging */
1946 return; /* no args ! */
1950 t = takeargs; /* list of those that take args */
1951 while (*s != '\0' && *(s+1) != '\0') {
1952 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1957 show_line(takeargs, 0);
1962 for (;;) { /* scan to end of command line args */
1963 if (*av[n] != '-') break;
1964 /* does it take an argument ? and is this argument next ? */
1966 *(av[n]+2) == '\0' &&
1967 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1968 strchr(takeargs, *(av[n]+1)) != NULL)
1969 n += 2; /* step over it */
1974 for (;;) { /* look for more command line args */
1977 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
1978 while (m < ac && *av[m] != '-') m++; /* first command */
1980 /* does it take an argument ? and is this argument next ? */
1981 /* check first whether the `-x' is isolated, or arg follows directly */
1982 /* then check whether this is one of those that takes an argument */
1984 *(av[m]+2) == '\0' &&
1985 strchr(takeargs, *(av[m]+1)) != NULL) {
1986 s = av[m]; /* move command down before non-command */
1988 for (; m > n; m--) av[m+1] = av[m-1];
1991 n += 2; /* step over moved args */
1994 s = av[m]; /* move command down before non-command */
1995 for (; m > n; m--) av[m] = av[m-1];
1997 n++; /* step over moved args */
2002 int test_align (int address, int size, char *name)
2005 if (size > 4) n = address % 4;
2006 else n = address % size;
2008 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2009 show_line(log_line, 0);
2014 /* activate detailed checking of alignment when trace_flag is set */
2016 void check_fixed_align (int flag)
2018 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2019 show_line("PLEASE RECOMPILE ME!\n", 1);
2021 #ifdef CHECKALIGNMENT
2023 test_align ((int) &mem_top, 4, "mem_top");
2024 test_align ((int) &mem_max, 4, "mem_max");
2025 test_align ((int) &mem_min, 4, "mem_min");
2026 test_align ((int) &bad, 4, "bad");
2027 test_align ((int) &trie_size, 4, "trie_size");
2028 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2029 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2030 test_align ((int) &name_length, 4, "name_length");
2031 test_align ((int) &first, 4, "first");
2032 test_align ((int) &last, 4, "last");
2033 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2034 test_align ((int) &pool_ptr, 4, "pool_ptr");
2035 test_align ((int) &str_ptr, 4, "str_ptr");
2036 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2037 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2038 test_align ((int) &log_file, 4, "log_file");
2039 test_align ((int) &tally, 4, "tally");
2040 test_align ((int) &term_offset, 4, "term_offset");
2041 test_align ((int) &file_offset, 4, "file_offset");
2042 test_align ((int) &trick_count, 4, "trick_count");
2043 test_align ((int) &first_count, 4, "first_count");
2044 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2045 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2046 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2047 test_align ((int) &use_err_help, 4, "use_err_help");
2048 test_align ((int) &interrupt, 4, "interrupt");
2049 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2050 test_align ((int) &arith_error, 4, "arith_error");
2051 test_align ((int) &tex_remainder, 4, "tex_remainder");
2052 test_align ((int) &temp_ptr, 4, "temp_ptr");
2053 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2054 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2055 test_align ((int) &var_used, 4, "var_used");
2056 test_align ((int) &dyn_used, 4, "dyn_used");
2057 test_align ((int) &avail, 4, "avail");
2058 test_align ((int) &mem_end, 4, "mem_end");
2059 test_align ((int) &mem_start, 4, "mem_start");
2060 test_align ((int) &rover, 4, "rover");
2061 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2062 test_align ((int) &depth_threshold, 4, "depth_threshold");
2063 test_align ((int) &breadth_max, 4, "breadth_max");
2064 test_align ((int) &nest, sizeof(nest[0]), "nest");
2067 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2069 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2070 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2071 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2072 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2074 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2075 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2076 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2077 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2078 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2079 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2080 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2081 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2083 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2084 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2085 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2086 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2087 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2088 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2089 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2090 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2091 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2092 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2093 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2094 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2095 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2096 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2097 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2098 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2099 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2100 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2101 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2102 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2103 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2104 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2105 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2106 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2108 #ifdef ALLOCATEDVIBUF
2109 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2111 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2112 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2113 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2114 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2115 test_align ((int) &background, sizeof(background[0]), "background");
2116 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2117 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2118 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2119 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2120 test_align ((int) &hc, sizeof(hc[0]), "hc");
2121 test_align ((int) &hu, sizeof(hu[0]), "hu");
2122 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2123 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2125 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2126 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2127 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2128 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2130 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2131 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2132 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2133 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2134 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2136 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2137 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2138 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2139 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2143 void check_alloc_align (int flag) {
2144 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2145 show_line("PLEASE RECOMPILE ME!\n", 1);
2146 #ifdef CHECKALIGNMENT
2149 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2151 #ifndef ALLOCATEDVIBUF
2152 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2154 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2155 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2156 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2157 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2158 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2159 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2160 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2161 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2162 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2163 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2164 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2165 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2166 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2167 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2168 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2173 void showaddresses (void)
2177 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2178 show_line(log_line, 0);
2179 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2180 show_line(log_line, 0);
2181 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2182 show_line(log_line, 0);
2183 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2184 save_stack, input_stack, line_stack, param_stack);
2185 show_line(log_line, 0);
2186 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2187 font_check, font_size, font_dsize, font_params, font_name);
2188 show_line(log_line, 0);
2189 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2190 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2191 show_line(log_line, 0);
2195 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2197 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2198 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2200 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2201 bool backwardflag = false; /* don't cripple all advanced features */
2202 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2203 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2204 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2205 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2206 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2207 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2208 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2209 bool workingdirectory = false; /* if working directory set in ini */
2211 /* set up full file name for dviwindo.ini and check for [Environment] */
2212 bool setupdviwindo (void)
2214 char dviwindoini[PATH_MAX];
2215 char line[PATH_MAX];
2218 int em = strlen(envsection);
2219 int wm = strlen(wndsection);
2220 int dm = strlen(workdirect);
2224 /* Easy to find Windows directory if Windows runs */
2225 /* Or if user kindly set WINDIR environment variable */
2226 /* Or if running in Windows NT */
2227 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2228 (windir = getenv("WINDIR")) != NULL ||
2229 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2230 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2231 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2232 strcpy(dviwindoini, windir);
2233 strcat(dviwindoini, "\\");
2234 strcat(dviwindoini, inifilename);
2235 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2239 _searchenv (inifilename, "PATH", dviwindoini);
2240 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2243 wndflag = envflag = 0;
2244 /* workingdirectory = false; */
2245 if (*dviwindoini != '\0') {
2246 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2247 /* check whether dviwindo.ini actually has [Environment] section */
2248 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2249 else pinput = _fsopen(dviwindo, "r", share_flag);
2250 if (pinput != NULL) {
2251 while (fgets (line, sizeof(line), pinput) != NULL) {
2252 if (*line == ';') continue;
2253 if (*line == '\n') continue;
2255 if (wndflag && envflag) break; /* escape early */
2257 if (_strnicmp(line, wndsection, wm) == 0) {
2259 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2260 show_line(log_line, 0);
2264 else if (_strnicmp(line, envsection, em) == 0) {
2266 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2267 show_line(log_line, 0);
2269 /* fclose(input); */
2272 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2274 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2275 show_line(log_line, 0);
2277 workingdirectory = true;
2281 (void) fclose(pinput);
2285 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2286 (void) fclose(pinput);
2288 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2289 strcpy(dviwindo, ""); /* failed, for one reason or another */
2294 /* cache to prevent allocating twice in a row */
2296 char *lastname=NULL, *lastvalue=NULL;
2298 /* get value of env var - try first in dviwindo.ini then DOS env */
2299 /* returns allocated string -- these strings are not freed again */
2300 /* is it safe to do that now ? 98/Jan/31 */
2301 char *grabenv (char *varname)
2303 char line[PATH_MAX];
2307 /* int m = strlen(envsection); */
2308 /* int n = strlen(varname); */
2310 if (varname == NULL) return NULL; /* sanity check */
2311 if (*varname == '\0') return NULL; /* sanity check */
2312 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2313 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2314 if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2316 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2317 show_line(log_line, 0);
2319 /* return lastvalue; */ /* save some time here */
2320 return xstrdup(lastvalue);
2321 /* duplicate so can free safely 98/Jan/31 */
2324 /* hmm, following was not xstrdup(...) */ /* not cached */
2325 if (usedviwindo == 0 || *dviwindo == '\0') {
2326 /* return getenv(varname); */
2327 s = getenv(varname);
2328 if (s == NULL) return NULL;
2329 else return xstrdup(s); /* make safe 98/Jan/31 */
2332 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2333 else pinput = _fsopen(dviwindo, "r", share_flag);
2335 if (pinput != NULL) {
2336 m = strlen(envsection);
2337 /* search for [Environment] section */ /* should be case insensitive */
2338 while (fgets (line, sizeof(line), pinput) != NULL) {
2339 if (*line == ';') continue;
2340 if (*line == '\n') continue;
2341 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2342 /* search for varname=... */ /* should be case sensitive ? */
2343 n = strlen(varname);
2344 while (fgets (line, sizeof(line), pinput) != NULL) {
2345 if (*line == ';') continue;
2346 if (*line == '[') break;
2347 /* if (*line == '\n') break; */ /* ??? */
2348 if (*line <= ' ') continue; /* 95/June/23 */
2349 /* if (strncmp(line, varname, n) == 0 && */
2350 if (_strnicmp(line, varname, n) == 0 &&
2351 *(line+n) == '=') { /* found it ? */
2352 (void) fclose (pinput);
2353 /* flush trailing white space */
2354 s = line + strlen(line) - 1;
2355 while (*s <= ' ' && s > line) *s-- = '\0';
2356 if (trace_flag) { /* DEBUGGING ONLY */
2357 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2358 show_line(log_line, 0);
2361 if (lastname != NULL) free(lastname);
2362 lastname = xstrdup (varname);
2363 if (lastvalue != NULL) free(lastvalue);
2364 lastvalue = xstrdup(s);
2365 return xstrdup(s); /* 98/Jan/31 */
2366 } /* end of matching varname */
2367 } /* end of while fgets */
2368 /* break; */ /* ? not found in designated section */
2369 } /* end of search for [Environment] section */
2371 (void) fclose (pinput);
2372 } /* end of if fopen */
2373 s = getenv(varname); /* failed, so try and get from environment */
2374 /* if (s != NULL) return s; */
2376 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2377 if (lastname != NULL) free(lastname);
2378 lastname = xstrdup (varname);
2379 if (lastvalue != NULL) free(lastvalue);
2380 lastvalue = xstrdup(s); /* remember in case asked again ... */
2382 return xstrdup(s); /* 98/Jan/31 */
2384 else return NULL; /* return NULL if not found anywhere */
2387 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2389 void flush_trailing_slash (char *directory)
2392 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2393 if (strcmp(directory, "") != 0) {
2394 s = directory + strlen(directory) - 1;
2395 if (*s == '\\' || *s == '/') *s = '\0';
2399 void knuthify (void)
2401 /* show_current = false; */ /* show ultimate limits */
2402 /* reorder_arg_flag = false; */ /* don't reorder command line */
2403 /* deslash = false; */ /* don't unixify file names */
2404 /* return_flag = false; */ /* don't allow just ^^M termination */
2405 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2406 restrict_to_ascii = false; /* don't complain non ASCII */
2407 allow_patterns = false; /* don't allow pattern redefinition */
2408 show_in_hex = true; /* show character code in hex */
2409 show_in_dos = false; /* redundant with previous */
2410 show_numeric = false; /* don't show character code decimal */
2411 show_missing = false; /* don't show missing characters */
2412 civilize_flag = false; /* don't reorder date fields */
2413 c_style_flag = false; /* don't add file name to error msg */
2414 show_fmt_flag = false; /* don't show format file in log */
2415 show_tfm_flag = false; /* don't show metric file in log */
2416 /* font_max = 255; */ /* revert to TeX 82 limit */
2417 /* if you want this, change in tex.h definition of font_max to `int' */
2418 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2420 show_line_break_stats = false; /* do not show line break stats */
2421 show_fonts_used = false;
2422 default_rule = 26214; /* revert to default rule thickness */
2423 pseudo_tilde = false;
2424 pseudo_space = false;
2425 show_texinput_flag = false;
2426 truncate_long_lines = false;
2427 allow_quoted_names = false;
2428 show_cs_names = false;
2429 font_dimen_zero = false; /* 98/Oct/5 */
2430 ignore_frozen = false; /* 98/Oct/5 */
2431 suppress_f_ligs = false; /* 99/Jan/5 */
2432 full_file_name_flag = false; // 00 Jun 18
2433 save_strings_flag = false; // 00 Aug 15
2434 knuth_flag = true; /* so other code can know about this */
2435 } /* end of knuthify */
2437 /* following have already been used up */
2439 /* abcdefghijklmnopqrstuvwxyz */
2441 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2445 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2447 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2449 /* following made global so analyze_flag can be made separate procedure */
2451 // char *xchrfile=""; /* save space use xstrdup */
2452 char *xchrfile = NULL; /* save space use xstrdup */
2453 // char *replfile="";/* save space use xstrdup */
2454 char *replfile = NULL;/* save space use xstrdup */
2456 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2458 /* analyze command line flag or argument */
2459 /* c is the flag letter itself, while optarg is start of arg if any */
2461 /* when making changes, revise allowedargs */
2464 int analyze_flag (int c, char *optarg)
2469 want_version = true;
2470 verbose_flag = true;
2476 interaction = batch_mode; /* quiet mode */
2479 interaction = nonstop_mode; /* run mode */
2482 interaction = scroll_mode; /* scroll mode */
2485 interaction = error_stop_mode; /* tex mode */
2488 backwardflag = true; /* 94/Jun/15 */
2489 knuthify(); /* revert to `standard' Knuth TeX */
2492 c_style_flag = true; /* C style error msg 94/Mar/21 */
2495 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2498 current_tfm = false; /* not look current dir for TFM */
2501 current_flag = false; /* not look current dir for files */
2504 show_missing = false; /* do not show missing 94/June/10 */
2507 deslash = false; /* flipped 93/Nov/18 */
2508 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2511 allow_patterns = true; /* 93/Nov/26 */
2512 /* reset_exceptions = true; */ /* 93/Dec/23 */
2514 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2516 show_in_hex = true; /* flipped 00/Jun/18 */
2519 show_in_dos = true; /* 96/Jan/26 */
2522 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2525 workingdirectory = true; /* use source dir 98/Sep/29 */
2528 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2531 show_fonts_used = false; /* 97/Dec/24 */
2534 shorten_file_name = true; /* 95/Feb/20 */
2537 show_cs_names = true; /* 98/Mar/31 */
2540 ignore_frozen = true; /* 98/Oct/5 */
2543 font_dimen_zero = false; /* 98/Oct/5 */
2546 show_texinput_flag = false; /* 98/Jan/28 */
2548 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2551 usedviwindo = false; /* 94/May/19 */
2554 show_line_break_stats = false; /* 96/Feb/8 */
2557 show_fmt_flag = false; /* 94/Jun/21 */
2560 format_specific = false; /* 95/Jan/7 */
2563 encoding_specific = false; /* 98/Oct/5 */
2566 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2568 /* following are pretty obscure */
2569 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2571 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2573 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2576 full_file_name_flag = false; // 00 Jun 18
2579 save_strings_flag = false; // 00 Aug 15
2581 /* following are unannounced options */ /* some may be recycled ... */
2586 quitflag++; /* 93/Dec/16 */
2588 /* The following are really obscure and should not be advertized */
2590 show_current = false; /* tex8 93/Dec/14 */
2593 show_numeric = false; /* 93/Dec/21 */
2596 civilize_flag = false; /* 93/Dec/16 */
2599 open_trace_flag = true; /* openinou 1994/Jan/8 */
2602 reorder_arg_flag = false; /* local */
2605 test_dir_access = false; /* 94/Feb/10 */
2608 dir_method = false; /* 94/Feb/10 */
2611 file_method = false; /* 94/Feb/13 */
2613 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2614 /* case 'X': nohandler++; break; */
2615 /* case 'f': waitflush = false; break; */
2616 /* case 'F': floating = true; break; */
2617 /* *********** following command line options take arguments ************** */
2620 mem_initex = mem_top;
2622 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2623 if (mem_initex == 0)
2624 complainarg(c, optarg);
2627 #ifdef VARIABLETRIESIZE
2630 trie_size = default_trie_size;
2632 trie_size = atoi(optarg); /* 93 Dec/1 */
2634 complainarg(c, optarg);
2637 #ifdef ALLOCATEHYPHEN
2640 new_hyphen_prime = hyphen_prime * 2;
2642 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2643 if (new_hyphen_prime == 0)
2644 complainarg(c, optarg);
2647 #ifdef ALLOCATEDVIBUF
2650 dvi_buf_size = default_dvi_buf_size;
2652 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2653 if (dvi_buf_size == 0)
2654 complainarg(c, optarg);
2661 percent_grow = atoi(optarg); /* 93/Dec/11 */
2662 if (percent_grow == 0)
2663 complainarg(c, optarg);
2669 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2670 if (pseudo_tilde > 255)
2672 else if (pseudo_tilde < 128)
2675 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2676 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2682 tab_step = atoi(optarg); /* 94/July/3 */
2684 complainarg(c, optarg);
2688 xchrfile = xstrdup("xchr.map");
2690 xchrfile = xstrdup(optarg);
2691 if (xchrfile == NULL || *xchrfile == '\0')
2692 complainarg(c, optarg);
2696 replfile = xstrdup("repl.key");
2698 replfile = xstrdup(optarg);
2699 if (replfile == NULL || *replfile == '\0')
2700 complainarg(c, optarg);
2702 /* more obscure stuff - ppssibly recycle */
2705 default_rule = 26214; /* 95/Oct/9 */
2707 default_rule = atoi(optarg); /* 95/Oct/9 */
2708 if (default_rule == 0)
2709 complainarg(c, optarg);
2715 complainarg(c, optarg);
2721 dvi_directory = xstrdup(optarg);
2722 if (strcmp(dvi_directory, "") == 0)
2723 complainarg(c, optarg);
2729 log_directory = xstrdup(optarg);
2730 if (strcmp(log_directory, "") == 0)
2731 complainarg(c, optarg);
2737 aux_directory = xstrdup(optarg);
2738 if (strcmp(aux_directory, "") == 0)
2739 complainarg(c, optarg);
2744 return -1; // failed to recognize
2750 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2751 //char *yytexcmd="yandytex.cmd";
2752 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2754 /* Try and read default command file - YANDYTEX.CMD */
2755 /* in current directory and then in directory of YANDYTEX */
2756 /* (does not make sense in TeX file directory) */
2757 /* since we don't yet know where that is ! */
2758 /* can't conveniently include this in output file either - not open yet */
2760 /* used both for yytex.cmd and @ indirect command line files */
2761 /* can this be reentered ? */
2763 /* supply extension if none */
2764 void yy_extension (char *fname, char *ext)
2767 if ((s = strrchr(fname, '.')) == NULL ||
2768 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2774 /* remove file name - keep only path - inserts '\0' to terminate */
2776 void strip_name (char *pathname)
2779 if ((s = strrchr(pathname, '\\')) != NULL);
2780 else if ((s = strrchr(pathname, '/')) != NULL);
2781 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2786 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2788 char *programpath = ""; /* pathname of program */
2789 /* redundant with texpath ? */
2791 /* The following does not deslashify arguments ? Do we need to ? */
2793 int read_commands (char *filename)
2795 char commandfile[PATH_MAX];
2797 char line[PATH_MAX];
2798 char *linedup; /* need to copy line to preserve args */
2804 /* Try first in current directory (or use full name as specified) */
2805 strcpy(commandfile, filename);
2806 yy_extension(commandfile, "cmd");
2807 if (share_flag == 0)
2808 command = fopen(commandfile, "r");
2810 command = _fsopen(commandfile, "r", share_flag);
2811 if (command == NULL) {
2812 /* If that fails, try in YANDYTeX program directory */
2813 strcpy(commandfile, programpath);
2814 /* don't need fancy footwork, since programpath non-empty */
2815 strcat(commandfile, "\\");
2816 strcat(commandfile, filename);
2817 yy_extension(commandfile, "cmd");
2818 if (share_flag == 0)
2819 command = fopen(commandfile, "r");
2821 command = _fsopen(commandfile, "r", share_flag);
2822 if (command == NULL) {
2823 /* perrormod(commandfile); */ /* debugging only */
2824 /* strcpy(commandfile, ""); */ /* indicate failed */
2825 return 0; /* no command line file YYTEX.CMD */
2829 /* allow for multiple lines --- ignore args that don't start with `-' */
2830 while (fgets(line, PATH_MAX, command) != NULL) {
2831 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2832 /* skip over comment lines and blank lines */
2833 if (*line == '%' || *line == ';' || *line == '\n') continue;
2834 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2835 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2836 linedup = xstrdup (line); /* 93/Nov/15 */
2837 if (linedup == NULL) {
2838 show_line("ERROR: out of memory\n", 1); /* read_commands */
2840 return -1; // failure
2842 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2844 if (*s == '-' || *s == '/') {
2847 /* if (*optarg = '=') optarg++; */
2848 if (*optarg == '=') optarg++;
2849 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2851 /* else break; */ /* ignore non-flag items */
2852 s = strtok(NULL, " \t\n\r"); /* go to next token */
2854 /* If you want to see command lines in file - put -v in the file */
2855 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2857 (void) fclose(command); /* no longer needed */
2858 return 1; // success
2861 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2863 /* try and read commands on command line */
2864 int read_command_line (int ac, char **av)
2867 char *optargnew; /* equal to optarg, unless that starts with `=' */
2868 /* in which case it is optarg+1 to step over the `=' */
2869 /* if optarg = 0, then optargnew = 0 also */
2871 // show_line("read_command_line\n", 0);
2872 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2874 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2875 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2876 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2877 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2878 if (optarg != 0 && *optarg == '=')
2879 optargnew = optarg+1;
2882 analyze_flag (c, optargnew);
2884 if (show_use || quitflag == 3) {
2885 // showversion (stdout);
2887 strcat(log_line, "\n");
2888 show_line(log_line, 0);
2889 stampcopy(log_line);
2890 strcat(log_line, "\n");
2891 show_line(log_line, 0);
2892 if (show_use) show_usage(av[0]);
2893 else if (quitflag == 3) {
2894 strcat(log_line, "\n");
2895 show_line(log_line, 0);
2898 return -1; // failure
2901 if (floating) testfloating(); /* debugging */
2904 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2905 if (read_xchr_file(replfile, 1, av)) {
2906 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2910 /* key_replace used in texmf.c (input_line) */
2911 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2912 if (read_xchr_file(xchrfile, 0, av)) {
2913 if (trace_flag) show_line("NON ASCII ON\n", 0);
2917 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2918 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2923 void uppercase (char *s)
2926 while ((c = *s) != '\0') {
2927 /* if (islower(c)) *s = toupper (*s); */
2934 int init_commands (int ac, char **av)
2936 /* NOTE: some defaults changed 1993/Nov/18 */
2937 /* want_version = show_use = switchflag = return_flag = false;
2938 is_initex = trace_flag = deslash = non_ascii = false; */
2939 is_initex = false; /* check for dumping format file */
2940 allow_patterns = false; /* using \pattern after format file loaded */
2941 reset_exceptions = false;
2943 key_replace = false;
2944 want_version = false;
2945 open_trace_flag = false;
2947 verbose_flag = false;
2949 restrict_to_ascii = false;
2950 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2951 show_in_dos = false; /* default is not to translate to DOS 850 */
2952 return_flag = true; // hard wired now
2953 trimeof = true; // hard wired now
2955 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2956 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2957 default_rule = 26214; /* default rule variable 95/Oct/9 */
2958 show_current = true;
2959 civilize_flag = true;
2960 show_numeric = true;
2961 show_missing = true;
2962 current_flag = true;
2963 current_tfm = true; /* search for TFMs in current dir as well */
2964 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2965 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2966 file_method = true; /* use file_p (_findfirst) not readable (access) */
2967 /* waitflush = true; */ /* flushed 97/Dec/24 */
2968 c_style_flag = false; /* use c-style error output */
2969 show_fmt_flag = true; /* show format file in log */
2970 show_tfm_flag = false; /* don't show metric file in log */
2971 shorten_file_name = false; /* don't shorten file names to 8+3 */
2972 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2973 truncate_long_lines = true; /* truncate long lines */
2974 tab_step = 0; /* do not replace tabs with spaces */
2975 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2976 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2977 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2978 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2979 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2980 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2981 knuth_flag = false; /* allow extensions to TeX */
2982 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2983 full_file_name_flag = true; /* new default 2000 June 18 */
2984 save_strings_flag = true; // 2000 Aug 15
2985 errout = stdout; /* as opposed to stderr say --- used ??? */
2986 abort_flag = 0; // not yet hooked up ???
2987 err_level = 0; // not yet hooked up ???
2988 new_hyphen_prime = 0;
2989 #ifdef VARIABLETRIESIZE
2990 /* trie_size = default_trie_size; */
2996 #ifdef ALLOCATEDVIBUF
2999 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
3000 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
3001 share_flag = 0; /* revert to fopen for now */
3003 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
3004 programpath = xstrdup(av[0]); /* extract path executable */
3005 strip_name(programpath); /* strip off yandytex.exe */
3007 //format_name = "yandytex";
3008 format_name = "plain"; /* format name if specified on command line */
3012 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
3013 return -1; // in case of error
3015 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
3016 return -1; // in case of error
3018 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
3020 /* Print version *after* banner ? */ /* does this get in log file ? */
3022 // showversion (stdout);
3023 // showversion (log_line);
3025 strcat(log_line, "\n");
3026 show_line(log_line, 0);
3027 stampcopy(log_line);
3028 strcat(log_line, "\n");
3029 show_line(log_line, 0);
3031 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
3033 /* if we aren't including current directory in any directory lists */
3034 /* then makes no sense to avoid them separately for TFM files ... */
3035 /* (that is, the ./ is already omitted from the dir list in that case */
3036 if (!current_flag && !current_tfm)
3037 current_tfm = true; /* 94/Jan/24 */
3038 return 0; // success
3041 /* E sets environment variable ? */
3043 void initial_memory (void)
3045 /* set initial memory allocations */
3046 if (mem_extra_high < 0)
3048 if (mem_extra_low < 0)
3054 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3055 if (mem_extra_high != 0 || mem_extra_low != 0)
3057 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3058 mem_extra_high = 0; mem_extra_low = 0;
3064 if (mem_initex != 0)
3066 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3071 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3072 /* trie_size = 0; */
3075 if (mem_initex == 0)
3076 mem_initex = default_mem_top;
3078 trie_size = default_trie_size;
3079 /* Just in case user mistakenly specified words instead of kilo words */
3080 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3081 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3082 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3083 #ifdef ALLOCATEHIGH /* not used anymore */
3084 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3085 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3086 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3089 #ifdef ALLOCATELOW /* not used anymore */
3090 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3091 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3092 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3095 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3096 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3097 /* mem_initex = 2048 * 1024; */
3099 #ifdef ALLOCATEDVIBUF
3100 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3101 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3102 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3103 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3104 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3106 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3107 if (new_hyphen_prime > 0) {
3109 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3111 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3112 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3114 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3115 show_line(log_line, 0);
3119 if (percent_grow > 100) percent_grow = percent_grow - 100;
3120 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3121 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3124 /**********************************************************************/
3126 void perrormod (char *s)
3128 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3129 show_line(log_line, 1);
3135 fflush(stdout); /* ??? */
3136 fflush(stderr); /* ??? */
3137 (void) _getch(); /* ??? */
3141 void checkpause (int flag)
3144 int debug_pause = 0;
3145 /* don't stop if in Q (quiet) or R (run) mode */
3146 /* stop only in S (scroll) and T (TeX) mode */
3147 if (interaction >= 0 && interaction < 2)
3148 flag = 0; /* 98/Jun/30 */
3149 s = grabenv("DEBUGPAUSE");
3150 if (s != NULL) sscanf(s, "%d", &debug_pause);
3151 if (flag < 0) return;
3153 if (debug_pause || flag > 0) {
3156 show_line("Press any key to continue . . .\n", 0);
3163 void check_enter (int argc, char *argv[])
3166 char current[FILENAME_MAX];
3167 if (grabenv("DEBUGPAUSE") != NULL) {
3168 (void) _getcwd(current, sizeof(current));
3169 sprintf(log_line, "Current directory: `%s'\n", current);
3170 show_line(log_line, 0);
3171 for (m = 0; m < argc; m++) {
3172 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3173 show_line(log_line, 0);
3180 void checkexit (int n)
3187 /*************************************************************************/
3189 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3190 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3191 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3192 /* this is then undone in tex3.c both for fopen input and output */
3193 /* not ideal, since pseudo name appears in log and in error messages ... */
3195 void hidetwiddle (char *name)
3200 sprintf(log_line, "Hidetwiddle %s", name);
3201 show_line(log_line, 0);
3204 /* while (*s != '\0' && *s != ' ') { */
3205 while (*s != '\0') {
3206 if (*s == '~' && pseudo_tilde != 0)
3207 *s = (char) pseudo_tilde; /* typically 254 */
3208 else if (*s == ' ' && pseudo_space != 0)
3209 *s = (char) pseudo_space; /* typically 255 */
3214 sprintf(log_line, "=> %s\n", name);
3215 show_line(log_line, 0);
3220 void deslash_all (int ac, char **av)
3222 char buffer[PATH_MAX];
3225 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3226 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3228 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3230 check_enter(ac, av); /* 95/Oct/28 */
3232 /* environment variables for output directories (as in PC TeX) */
3234 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3235 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3236 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3238 strcpy(buffer, av[0]); /* get path to executable */
3239 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3240 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3241 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3242 s = buffer + strlen(buffer) - 1;
3243 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3244 texpath = xstrdup(buffer);
3246 /* Hmm, we may be operating on DOS environment variables here !!! */
3248 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3249 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3250 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3253 unixify (texpath); /* 94/Jan/25 */
3254 /* if output directories given, deslashify them also 1993/Dec/12 */
3255 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3256 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3257 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3260 /* deslash TeX source file (and format, if format specified) */
3261 /* and check args to see whether format was specified */
3263 /* NOTE: assuming that command line arguments are in writable memory ! */
3264 /* if (trace_flag || debug_flag)
3265 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3266 /* if (optind < ac) { */ /* bkph */
3267 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3269 if (trace_flag || debug_flag) {
3270 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3271 optind, av[optind], ac);
3272 show_line(log_line, 0);
3274 unixify(av[optind]);
3276 if (pseudo_tilde != 0 || pseudo_space != 0)
3277 hidetwiddle (av[optind]); /* 95/Sep/25 */
3278 /* For Windows NT, lets allow + instead of & for format specification */
3279 if (*av[optind] == '&' || *av[optind] == '+') {
3280 format_spec = 1; /* format file specified */
3281 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3282 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3283 if (optind + 1 < ac) {
3285 if (trace_flag || debug_flag) {
3286 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3287 optind+1, av[optind+1], ac);
3288 show_line(log_line, 0);
3290 unixify(av[optind+1]);
3292 if (pseudo_tilde != 0 || pseudo_space != 0)
3293 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3299 /* The above seems to assume that arguments that don't start with '-' */
3300 /* are file names or format names - what if type in control sequences? */
3302 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3304 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3305 /* interaction == 1 => nonstop mode (omit all stops) */
3306 /* interaction == 2 => scroll mode (omit error stops) */
3307 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3309 /* main entry point follows */
3311 /* this gets called pretty much right away in `main' in texmf.c */
3313 /* note: those optarg == 0 test don't really work ... */
3314 /* note: optarg starts at = in case of x=... */
3316 int init (int ac, char **av)
3318 char initbuffer[PATH_MAX];
3321 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3328 show_line("TEXDEBUG\n", 0);
3329 trace_flag = 1; /* 94/April/14 */
3332 if (sizeof(memory_word) != 8) { /* compile time test */
3333 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3334 show_line(log_line, 1);
3337 start_time = clock(); /* get time */
3338 main_time = start_time; /* fill in, in case file never opened */
3340 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3342 /* reset all allocatable memory pointers to NULL - in case we drop out */
3347 #ifdef ALLOCATEZEQTB
3353 #ifdef ALLOCATESAVESTACK
3356 #ifdef ALLOCATEDVIBUF
3359 #ifdef ALLOCATEBUFFER
3360 buffer = NULL; /* new 1999/Jan/7 need to do early */
3361 current_buf_size = 0;
3362 buffer = realloc_buffer (initial_buf_size);
3363 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3365 hyph_list = NULL; hyph_word = NULL;
3366 trie_taken = NULL; trie_hash = NULL;
3375 log_opened = false; /* so can tell whether opened */
3376 interaction = -1; /* default state => 3 */
3377 missing_characters = 0; /* none yet! */
3378 workingdirectory = false; /* set from dviwindo.ini & command line */
3379 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3380 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3381 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3382 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3383 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3385 if (reorder_arg_flag) reorderargs(ac, av);
3387 if (init_commands(ac, av))
3388 return -1; // failure
3390 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3392 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3393 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3394 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3395 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3396 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3398 first_pass_count = 0;
3399 second_pass_count = 0;
3400 final_pass_count = 0;
3401 paragraph_failed = 0;
3408 closed_already=0; // so can only do once
3410 if (trace_flag) show_line("Entering init (local)\n", 0);
3412 /* Print version *after* banner ? */ /* does this get in log file ? */
3414 probe_memory(); /* show top address */
3415 ini_max_address = max_address; /* initial max address */
3416 if (trace_flag) show_maximums(stdout);
3418 if (heap_flag) (void) heap_dump(stdout, 1);
3423 deslash_all(ac, av); /* deslash and note if format specified */
3425 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3429 if (format_spec && mem_spec_flag) {
3430 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3433 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3434 return -1; // if failed to allocate
3436 /* following is more or less useless since most all things not yet alloc */
3437 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3439 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3443 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3446 if (trace_flag) show_line("Leaving init (local)\n", 0);
3447 return 0; // success
3450 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3452 /* void show_inter_val (clock_t start, clock_t end) { */
3453 void show_inter_val (clock_t interval)
3455 /* clock_t interval; */
3456 /* int seconds, tenths; */
3457 /* int seconds, tenths, hundredth; */
3458 int seconds, tenths, hundredth, thousands;
3459 /* interval = end - start; */
3460 /* sanity check whether positive ? */
3461 if (interval >= CLK_TCK * 10) {
3462 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3463 seconds = tenths / 10;
3464 tenths = tenths % 10;
3465 sprintf(log_line, "%d.%d", seconds, tenths);
3466 show_line(log_line, 0);
3468 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3469 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3470 seconds = hundredth / 100;
3471 hundredth = hundredth % 100;
3472 sprintf(log_line, "%d.%02d", seconds, hundredth);
3473 show_line(log_line, 0);
3475 else if (interval > 0) { /* 94/Oct/4 */
3476 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3477 seconds = thousands / 1000;
3478 thousands = thousands % 1000;
3479 sprintf(log_line, "%d.%03d", seconds, thousands);
3480 show_line(log_line, 0);
3482 else show_line("0", 0); /* 95/Mar/1 */
3485 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3486 /* shows various times, warning about missing chars */
3488 int endit (int flag)
3491 finish_time = clock();
3492 if (missing_characters != 0) flag = 1;
3493 if (missing_characters) {
3495 "! There %s %d missing character%s --- see log file\n",
3496 (missing_characters == 1) ? "was" : "were", missing_characters,
3497 (missing_characters == 1) ? "" : "s");
3498 show_line(log_line, 0);
3500 if (free_memory() != 0) flag++;
3502 /* show per page time also ? */
3504 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3505 start_time, main_time, finish_time); */
3506 show_line("Total ", 0);
3507 /* show_inter_val(start_time, finish_time); */
3508 show_inter_val(finish_time - start_time);
3509 show_line(" sec (", 0);
3510 /* show_inter_val(start_time, main_time); */
3511 show_inter_val(main_time - start_time);
3512 show_line(" format load + ", 0);
3513 /* show_inter_val(main_time, finish_time); */
3514 show_inter_val(finish_time - main_time);
3515 show_line(" processing) ", 0);
3516 if (total_pages > 0) {
3517 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3518 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3519 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3520 show_inter_val ((finish_time - main_time) / total_pages);
3521 show_line(" sec per page", 0);
3531 /********************************************************************************/
3533 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3537 #define MAXCOLUMN 78
3539 void print_cs_name (FILE *output, int h)
3544 textof = hash[h].v.RH;
3545 if (textof == 0) return; /* ignore if text() == 0 */
3547 if (textcolumn != 0) {
3548 sprintf(log_line, ", ");
3549 if (output != NULL) fprintf(output, log_line);
3550 else show_line(log_line, 0);
3553 if (textcolumn + n + 2 >= MAXCOLUMN) {
3554 sprintf(log_line, "\n");
3555 if (output == stderr) show_line(log_line, 1);
3556 else if (output == stdout) show_line(log_line, 0);
3557 else fputs(log_line, output);
3561 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3564 if (output == stderr) show_line(log_line, 1);
3565 else if (output == stdout) show_line(log_line, 0);
3566 else fprintf(output, log_line);
3570 int compare_strn (int, int, int, int); /* in tex9.c */
3572 /* compare two csnames in qsort */
3574 int compare_cs (const void *cp1, const void *cp2)
3576 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3579 textof1 = hash[c1].v.RH;
3580 textof2 = hash[c2].v.RH;
3581 l1 = length(textof1);
3582 l2 = length(textof2);
3583 k1 = str_start[textof1];
3584 k2 = str_start[textof2];
3585 /* showstring (k1, l1); */
3586 /* showstring (k2, l2); */
3587 return compare_strn (k1, l1, k2, l2);
3592 /* Allocate table of indeces to allow sorting on csname */
3593 /* Allocate flags to remember which ones already listed at start */
3595 void print_cs_names (FILE *output, int pass)
3597 int h, k, ccount, repeatflag;
3599 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3601 if (pass == 0 && csused == NULL) {
3602 csused = (char *) malloc (nfcs);
3603 if (csused == NULL) return;
3605 memset(csused, 0, nfcs);
3607 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3612 for (h = hash_base + 1; h < nfcs; h++) {
3613 if (pass == 1 && csused[h]) continue;
3614 if (hash[h].v.RH != 0) {
3615 if (pass == 0) csused[h] = 1;
3620 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3621 ccount, (pass == 1) ? "new" : "");
3622 if (output == stderr) show_line(log_line, 1);
3623 else if (output == stdout) show_line(log_line, 0);
3624 else fprintf(output, log_line);
3626 if (ccount > 0) { /* don't bother to get into trouble */
3628 cnumtable = (int *) malloc (ccount * sizeof(int));
3629 if (cnumtable == NULL) return;
3632 /* for (h = 515; h < (hash_size + 780); h++) { */
3633 for (h = hash_base+1; h < nfcs; h++) {
3634 if (pass == 1 && csused[ h]) continue;
3635 if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3638 qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3641 for (k = 0; k < ccount; k++) {
3643 if (pass == 1 && csused[ h]) continue;
3644 print_cs_name(output, h);
3646 sprintf(log_line, "\n");
3647 if (output == stderr) show_line(log_line, 1);
3648 else if (output == stdout) show_line(log_line, 0);
3649 else fprintf(output, log_line);
3650 free((void *)cnumtable);
3653 if (pass == 1 && csused != NULL) {
3659 /***************** font info listing moved from TEX9.C ******************/
3661 void showstring (int k, int l)
3664 while (l-- > 0) *s++ = str_pool[k++];
3667 show_line(log_line, 0);
3670 /* compare two strings in str_pool (not null terminated) */
3671 /* k1 and k2 are positions in string pool */
3672 /* l1 and l2 are lengths of strings */
3674 int compare_strn (int k1, int l1, int k2, int l2)
3677 /* while (l1-- > 0 && l2-- > 0) { */
3678 while (l1 > 0 && l2 > 0) {
3681 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3682 if (c1 > c2) return 1;
3683 else if (c2 > c1) return -1;
3687 if (l1 > 0) return 1; /* first string longer */
3688 else if (l2 > 0) return -1; /* second string longer */
3689 return 0; /* strings match */
3692 /* compare two font names and their at sizes in qsort */
3694 int compare_fnt (const void *fp1, const void *fp2)
3696 int f1, f2, l1, l2, k1, k2, s;
3699 l1 = length(font_name[f1]);
3700 l2 = length(font_name[f2]);
3701 k1 = str_start[font_name[f1]];
3702 k2 = str_start[font_name[f2]];
3703 /* showstring (k1, l1); */
3704 /* showstring (k2, l2); */
3705 s = compare_strn (k1, l1, k2, l2);
3706 /* sprintf(log_line, "%d\n", s); */
3707 if (s != 0) return s;
3708 if (font_size[f1]> font_size[f2]) return 1;
3709 else if (font_size[f1]< font_size[f2]) return -1;
3710 return 0; /* should not ever get here */
3713 /* compare two font names */
3715 int compare_fnt_name (int f1, int f2)
3717 int l1, l2, k1, k2, s;
3718 l1 = length(font_name[f1]);
3719 l2 = length(font_name[f2]);
3720 k1 = str_start[font_name[f1]];
3721 k2 = str_start[font_name[f2]];
3722 /* showstring (k1, l1); */
3723 /* showstring (k2, l2); */
3724 s = compare_strn (k1, l1, k2, l2);
3725 /* sprintf(log_line, "%d\n", s); */
3729 /* decode checksum information */
3731 unsigned long checkdefault = 0x59265920; /* default signature */
3733 int decode_fourty (unsigned long checksum, char *codingvector)
3737 /* char codingvector[6+1]; */
3739 /* if (checksum == checkdefault) { */
3740 if (checksum == 0) {
3741 /* strcpy(codingvector, "unknown"); */
3742 strcpy(codingvector, "unknwn");
3745 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3746 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3747 strcpy (codingvector, "fixed "); /* if not specified ... */
3748 return 1; /* no info available */
3751 for (k = 0; k < 6; k++) {
3752 c = (int) (checksum % 40);
3753 checksum = checksum / 40;
3754 if (c <= 'z' - 'a')c = c + 'a';
3755 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3756 else if (c == 36) c = '-';
3757 else if (c == 37) c = '&';
3758 else if (c == 38) c = '_';
3759 else c = '.'; /* unknown */
3760 codingvector[5-k] = (char) c;
3762 codingvector[6] = '\0';
3764 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3765 return 0; /* encoding info returned in codingvector */
3768 double sclpnt (long x)
3771 pt = (double) x / 65536.0;
3772 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3776 // Shows list of fonts in log file
3778 void dvi_font_show(internal_font_number f, int suppressname)
3780 int a, l, k, n, for_end;
3781 unsigned long checksum;
3782 char checksumvector[8];
3785 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3786 /* fprintf (log_file, "%d ", suppressname); */
3787 /* suppressname = 0; */
3788 putc(' ', log_file);
3789 if (suppressname == 0) {
3790 a = length(font_area[f]);
3791 l = length(font_name[f]);
3792 k = str_start[font_area[f]];
3793 for_end = str_start[font_area[f]+ 1]- 1;
3794 if (k <= for_end) do {
3795 putc(str_pool[k], log_file);
3796 } while(k++ < for_end, stdout);
3797 k = str_start[font_name[f]];
3798 for_end = str_start[font_name[f]+ 1]- 1;
3799 if (k <= for_end) do {
3800 putc(str_pool[k], log_file);
3801 } while(k++ < for_end);
3804 for (k = a+l; k < 16; k++) putc(' ', log_file);
3805 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3806 fputs(buffer, log_file);
3807 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3808 if (suppressname == 0) {
3810 // n = strlen(log_file);
3811 for (k = n; k < 16; k++) putc(' ', log_file);
3812 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3813 font_check[f].b2) << 8 | font_check[f].b3;
3814 decode_fourty(checksum, checksumvector);
3815 fprintf(log_file, "encoding: %s..", checksumvector);
3817 putc('\n', log_file);
3820 /* Allocate table of indeces to allow sorting on font name */
3822 void show_font_info (void)
3824 int k, m, fcount, repeatflag;
3828 for (k = 1; k <= font_ptr; k++)
3829 if (font_used[k])fcount++;
3831 if (fcount == 0) return; /* don't bother to get into trouble */
3833 fnumtable = (short *) malloc (fcount * sizeof(short));
3835 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3837 fprintf(log_file, "\nUsed %d font%s:\n",
3838 fcount, (fcount == 1) ? "" : "s");
3841 for (k = 1; k <= font_ptr; k++)
3842 if (font_used[k])fnumtable[fcount++] = (short) k;
3844 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3847 for (m = 0; m < fcount; m++) {
3849 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3851 else repeatflag = 0;
3853 dvi_font_show(fnumtable[ m], repeatflag);
3856 free((void *)fnumtable);
3859 ////////////////////////////////////////////////////////////////////////////
3861 // Here follows the new stuff for the DLL version
3867 #define SHOWLINEBUFLEN 256
3869 char showlinebuf[SHOWLINEBUFLEN];
3871 // char log_line[MAXLINE];
3873 #define WHITESPACE " \t\n\r"
3875 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3877 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3879 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3880 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3881 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3883 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3885 void ClearShowBuffer (void)
3887 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3888 if (hConsoleWnd != NULL)
3889 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3893 // communicate with DVIWindo (for yandytex.dll)
3895 void show_line (char *line, int errflag) { /* 99/June/11 */
3898 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3899 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3900 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3902 // abort_flag++; // kill job in this case ???
3906 if (showlineinx > 0) ClearShowBuffer();
3908 if (hConsoleWnd != NULL)
3909 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3913 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3914 if (ret == IDCANCEL) {
3916 uexit(1); // dangerous reentry possibility ?
3921 // Provide means for buffering up individual characters
3923 void show_char (int chr) {
3924 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3925 showlinebuf[showlineinx++] = (char) chr;
3926 if (chr == '\n') ClearShowBuffer();
3929 void winshow(char *line) {
3930 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3933 void winerror (char *line) {
3935 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3936 if (ret == IDCANCEL) abort_flag++;
3939 // argument info constructed from command line
3945 // need to be careful here because of quoted args with spaces in them
3946 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3948 int makecommandargs (char *line)
3952 unsigned char *s, *t; // fix 2000 June 18
3954 if (line == NULL) return -1; /* sanity check */
3956 // winerror(line); // debugging only
3958 // s = strtok(line, WHITESPACE);
3959 // while (s != NULL) { /* count arguments */
3961 // s = strtok(NULL, WHITESPACE);
3966 while (*s != '\0') {
3967 while (*s <= 32 && *s > 0) s++;
3968 if (*s == '\0') break;
3970 while (*t > 32 && *t != '\"') t++;
3973 while (*t > 0 && *t != '\"') t++;
3974 if (*t == '\0') break;
3977 // xargv[xargc] = s;
3979 if (*t == '\0') break;
3984 if (xargc == 0) return -1; /* nothing to do */
3986 xargv = (char **) malloc(xargc * sizeof(char *));
3987 if (xargv == NULL) {
3988 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3995 while (*s != '\0') {
3996 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3997 if (*s == '\0') break;
3999 while (*t > ' ' && *t != '\"') t++;
4002 while (*t > 0 && *t != '\"') t++;
4003 if (*t == '\0') break;
4006 // winerror(s); // debugging only
4009 if (*t == '\0') break;
4015 // for (k = 0; k < xargc; k++) { /* create pointers to args */
4016 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
4018 // s += strlen(s) +1;
4024 for (k = 0; k < xargc; k++) {
4025 sprintf(s, "%d\t%s\n", k, xargv[k]);
4033 // refers to TeXAsk in dviwindo.c
4035 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4036 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
4038 // called from tex0.c only --- by initterm and term_input
4040 //int ConsoleInput (char *question, char *buffer)
4041 int ConsoleInput (char *question, char *help, char *buffer)
4045 if (AskUserCall == NULL) return 0;
4046 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4047 // show_line(log_line, 1);
4050 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
4051 // strcpy(buffer, "x");
4052 // strcat(buffer, " "); // ???
4053 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4054 // show_line(log_line, 1);
4055 // input_line_finish(); // ???
4056 // s = buffer + strlen(buffer);
4057 // *s++ = ' '; // space terminate
4058 // *s++ = '\0'; // and null terminate
4059 // returning != 0 means EOF or ^Z
4063 // This is the new entry point of DLL called from DVIWindo
4064 // ARGS: console window to send messages to, command line, callback fun
4065 // no console window output if hConsole is NULL
4066 // returns -1 if it fails --- returns 0 if it succeeds
4068 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4069 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4073 abort_flag = 0; // redundant
4074 hConsoleWnd = NULL; // redundant
4076 AskUserCall = AskUser; // remember callback
4078 hConsoleWnd = hConsole; // remember console window handle
4080 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4081 // if (grabenv("DEBUGPAUSE") != NULL) {
4082 // show_line(line, 0); // debugging - show command line
4083 // show_line("\n", 0);
4086 xargc = makecommandargs(line); // sets up global *xargv[]
4088 if (xargc < 0) return -1; // sanity check
4090 if (hConsoleWnd != NULL)
4091 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4092 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4095 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
4097 if (err_level > 0 || abort_flag > 0) {
4098 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4099 // err_level, abort_flag);
4100 // winerror(log_line);
4103 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
4104 // if (psbufpos > 0) PSputs("", output); // output already closed
4106 if (hConsoleWnd != NULL) {
4107 if (err_level > 0 || abort_flag > 0) flag = 1;
4108 else flag = 0; // pass along error indication
4109 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
4111 // PScallback = NULL;
4114 if (xargv != NULL) free(xargv);
4115 if (abort_flag) return -1;
4119 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4122 switch (fdwReason) {
4123 case DLL_PROCESS_ATTACH:
4124 // The DLL is being mapped into the process's address space
4125 // place to allocate memory ???
4126 // return FALSE if this fails
4127 hInstanceDLL = hInstDll; /* remember it */
4130 case DLL_THREAD_ATTACH:
4131 // A thread is being created
4134 case DLL_THREAD_DETACH:
4135 // A thread is exiting cleanly
4138 case DLL_PROCESS_DETACH:
4139 // The DLL is being unmapped from the process's address space
4140 // place to free any memory allocated
4141 // but make sure it in fact *was* allocated
4142 hInstanceDLL = NULL; /* forget it */
4145 return(TRUE); // used only for DLL_PROCESS_ATTACH
4147 #endif // end of new stuff for DLL version
4149 //////////////////////////////////////////////////////////////////////////////
4153 /* NOTE: current_tfm = false (-c)
4154 not checking for TFM in current directory saves 0.1 sec
4155 (0.2 if file_method = false (-G) */
4157 /* NOTE: test_dir_access = false (-b):
4158 not checking whether readable file is a directory saves maybe 0.5 sec
4159 BUT only if file_method = false (-G) - otherwise its irrelevant */
4161 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4162 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4163 BUT not if current_tfm = false (-c) */
4165 /* NOTE: file_method = false (-G) --- method for checking file accessible
4166 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4168 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4170 /* constants for _heapchk/_heapset/_heapwalk routines */
4171 /* #define _HEAPEMPTY (-1) */
4172 /* #define _HEAPOK (-2) */
4173 /* #define _HEAPBADBEGIN (-3) */
4174 /* #define _HEAPBADNODE (-4) */
4175 /* #define _HEAPEND (-5) */
4176 /* #define _HEAPBADPTR (-6) */
4178 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4180 /* buffercopy no longer used */
4182 /* To Knuthian reset right when command line interpreted */