OSDN Git Service

cur_glue and cur_g.
[putex/putex.git] / src / texsourc / local.c
1 /* Copyright 2007 TeX Users Group
2    Copyright 2014 Clerk Ma   
3
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.
8
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.
13
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
17    02110-1301 USA.  */
18
19 #ifdef _WINDOWS
20   #define NOCOMM
21   #define NOSOUND
22   #define NODRIVERS
23   #define STRICT
24   #pragma warning(disable:4115) // kill rpcasync.h complaint
25   #include <windows.h>
26   #define MYLIBAPI __declspec(dllexport)
27 #endif
28
29 #include "texwin.h"
30
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
35
36 #include <setjmp.h>
37
38 #define EXTERN extern
39
40 #include "texd.h"
41
42 /* Most Y & Y changes are localized here -- init() */
43
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 */ 
48
49 #define USEOUREALLOC      /* 96/Jan/20 */
50
51 #define USEMEMSET       /* 98/Jan/23 */
52
53 /* #define PREALLOCHOLE */    /* make hole in heap at bottom debugging */
54
55 /* #define CHECKALIGNMENT */  /* reactivated 95/Jan/7 */
56
57 /* #define HEAPSHOW */      /* debugging 96/Jan/20 */
58
59 /* #ifdef TRYANDOPEN */     /* debugging only */
60
61 /* #define SHOWHEAPERROR */   /* debugging 96/Jan/10 */
62
63 #ifndef _WINDOWS
64 /* #define HEAPWALK */      /* debugging 96/Oct/22 */
65 #endif
66
67 #ifdef USEOUREALLOC
68   #define REALLOC ourrealloc
69 #else
70   #define REALLOC realloc
71 #endif
72
73 #include <time.h>
74 #include <malloc.h> /* _msize, _expand, HEAPOK et.c */
75 #include <direct.h> /* for _getcwd() */
76
77 #pragma warning(disable:4032) // different type when promoted
78 #ifndef _WINDOWS
79   #include <conio.h>            /* for _getch() */
80 #endif
81 #pragma warning(default:4032) // different type when promoted
82
83
84 /* Argument handling, etc.  */ /* from common.h - setup `main' in texmf.c */
85 /* extern int gargc; */
86 /* extern char **gargv; */
87
88 int wantcopyrght=1;
89
90 /* appears in reverse order in EXE file */
91
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";
106
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
114
115 clock_t start_time, main_time, finish_time;
116
117 char *dvi_directory = ""; /* user specified directory for dvi file */
118 char *log_directory = ""; /* user specified directory for log file */
119 char *aux_directory = ""; /* user specified directory for aux file */
120
121 char *texpath = "";   /* path to executable - used if env vars not set */
122
123 // #define MAXLINE 256
124
125 char log_line[MAXLINE];  // used also in tex9.c
126
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 */
131
132 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
133 /* Used in tex0.c with wintodos[c-128]                      */
134
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
152 };  
153
154 void show_usage (char * program)
155 {
156   char * s = log_line;
157   sprintf (s, "\n"
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)");
178   strcat(s, "\n");
179   show_line(log_line, 1);
180 #ifndef _WINDOWS
181   uexit(1);     // has this been setup yet ???
182 #endif
183 }
184
185 /* -z    do not discard control-Z at end of input file (treat as character)\n\ */
186
187 /* -c    prepend current directory (.) to TFM directory list\n\ */
188 /* -b    check that files with read access are not actually directories\n\ */
189
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\ */
193
194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
195
196 /* Sep 27 1990 => 1990 Sep 27 */
197 /* 012456789      0123456789  */
198
199 void scivilize (char * date)
200 {
201   int k;
202   char pyear[6];
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];
206   date[4] = ' ';
207   if (date[9] == ' ') date[9] = '0'; /* replace space by '0' */
208   return;
209 }
210
211 /* Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35 */
212
213 void lcivilize (char * date)
214 {
215   int k;
216   char pyear[6];
217
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'; */
222   date[20] = '\0'; 
223   for (k = 0; k < 4; k++) date[k] = pyear[k];
224   date[4] = ' ';
225   return;
226 }
227
228 // void stamp_it (FILE *outfile)
229 // now writes result into given buffer
230 void stamp_it (char *s)
231 {
232   char date[11 + 1];
233
234   strcpy(date, compiledate);
235   scivilize(date);
236   sprintf(s, "%s %s ", application, yandyversion);
237   s += strlen(s);
238   sprintf(s, "(compiled time: %s %s)", date, compiletime);
239   s += strlen(s);
240 }
241
242 void stampcopy (char *s)
243 {
244   if (wantcopyrght)
245   {
246     sprintf(s, "%s %s", copyright, www);    /* 99/Oct/25 */
247   }
248 }
249
250 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
251
252 #define MAXCHRS 256
253 #define NOTDEF 127
254
255 void read_xchr_sub (FILE * xchr_input)
256 {
257   char buffer[PATH_MAX];
258   int k, from, to, count = 0;
259   char *s;
260
261 #ifdef USEMEMSET
262   memset (xchr, NOTDEF, MAXCHRS);           /* mark unused */
263 #else
264   for (k = 0; k < MAXCHRS; k++) xchr[k]= -1; /* mark unused */
265 #endif
266 #ifdef USEMEMSET
267   memset (xord, NOTDEF, MAXCHRS);           /* mark unused */
268 #else
269   for (k = 0; k < MAXCHRS; k++) xord[k]= -1;  /* mark unused */
270 #endif
271
272 #ifdef ALLOCATEBUFFER
273   while (fgets(buffer, current_buf_size, xchr_input) != NULL) 
274 #else
275   while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
276 #endif
277   {
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;
287       else {
288         sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
289         show_line(log_line, 0);
290       }
291       if (xord[to]== NOTDEF)
292         xord[to]= (unsigned char) from;
293       else {
294         sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
295         show_line(log_line, 0);
296       }
297       count++;
298     }
299   }
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 */
306       }
307     }
308   }
309   xchr[NOTDEF]= NOTDEF;         /* fixed point of mapping */
310   if (trace_flag) {
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);
317       }
318     }
319   }
320 }
321
322 char *replacement[MAXCHRS];     /* pointers to replacement strings */
323
324 void read_repl_sub (FILE * repl_input)
325 {
326   int k, n, m, chrs;
327   char buffer[PATH_MAX];
328   char charname[128];
329   int charnum[10];
330   char *s, *t;
331   
332 #ifdef USEMEMSET
333   memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
334 #else
335   for (k = 0; k < MAXCHRS; k++) replacement[k] = NULL; 
336 #endif
337
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)
341       continue; 
342     else if (m == 2) {
343       if (*charname == '"') {   /* deal with quoted string "..." */
344         s = buffer + n;
345         t = charname;
346         while (*s != '"' && *s != '\0') s++;  /* step up to " */
347         if (*s++ == '\0') continue;       /* sanity check */
348         while (*s != '\0') {  
349           if (*s == '"') {
350             s++;            /* is it "" perhaps ? */
351             if (*s != '"') break;   /* no, end of string */
352           }
353           *t++ = *s++;          /* copy over */
354         }
355         *t = '\0';              /* and terminate */
356       }
357       if (chrs >= 0 && chrs < MAXCHRS)
358         replacement[chrs] = xstrdup(charname);
359     }
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];
367       charname[m] = '\0';
368       if (chrs >= 0 && chrs < MAXCHRS)
369         replacement[chrs] = xstrdup(charname);      
370     }
371     else {
372       sprintf(log_line, "ERROR: don't understand %s", buffer);
373       show_line(log_line, 1);
374     }
375   }
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);
382       }
383     }
384   }
385 }
386
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=... */
389
390 int read_xchr_file (char *filename, int flag, char *argv[])
391 {
392   FILE *pinput;
393   char infile[PATH_MAX];
394   char *s;
395
396   if (filename == NULL) return -1;
397   if (trace_flag) {
398     sprintf(log_line, "Reading xchr/repl %s\n", filename);
399     show_line(log_line, 0);
400   }
401
402 /*  first try using file as specified */
403   strcpy(infile, filename);
404   if (trace_flag) {
405     sprintf(log_line, "Trying %s\n", infile);
406     show_line(log_line, 0);
407   }
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");
414       if (trace_flag) {
415         sprintf(log_line, "Trying %s\n", infile);
416         show_line(log_line, 0);
417       }
418       if (share_flag == 0) pinput = fopen (infile, "r");
419       else pinput = _fsopen (infile, "r", share_flag);  /* 94/July/12 */
420     }
421   }
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);
429     if (trace_flag) {
430       sprintf(log_line, "Trying %s\n", infile);
431       show_line(log_line, 0);
432     }
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");
439         if (trace_flag) {
440           sprintf(log_line, "Trying %s\n", infile);
441           show_line(log_line, 0);
442         }
443         if (share_flag == 0) pinput = fopen (infile, "r");
444         else pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
445       }
446     }
447   }
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);
456     if (trace_flag) {
457       sprintf(log_line, "Trying %s\n", infile);
458       show_line(log_line, 0);
459     }
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");
466         if (trace_flag) {
467           sprintf(log_line, "Trying %s\n", infile);
468           show_line(log_line, 0);
469         }
470         if (share_flag == 0) pinput = fopen (infile, "r");
471         else pinput = _fsopen (infile, "r", share_flag);
472       }
473     }
474   }
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);
481     return 0;         // failed
482   }
483
484   if (flag == 0)
485     read_xchr_sub (pinput);
486   else
487     read_repl_sub (pinput);
488
489   (void) fclose (pinput);
490   return 1;
491 }
492
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 */
496
497 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
498
499 /* Following may be useful if link without floating point emulation */
500
501 #ifdef DEBUG
502 void testfloating (void) {
503 /*  double x = 1.0; */
504 /*  double dx = DBL_EPSILON; */
505   double dx = 1.0;
506   double dxold = 0.0;
507   int k = 0;
508 /*  while (x + dx != 1.0) { */
509   while (1.0 + dx != 1.0) {
510     dxold = dx;
511     dx = dx / 2.0;
512     k++;
513   }
514   sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
515   show_line(log_line, 0);
516 }
517 #endif
518
519 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
520
521 char *debugfile;      /* NULL or name of file to try and open */
522
523 #ifdef SHOWHEAPERROR
524   char *heapstrings[] = {
525     "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
526   };
527 #endif
528
529 /* Attempt to get at problem with eqtb ... temporarily abandoned */
530
531 #ifdef CHECKEQTB
532 void check_eqtb (char *act) {
533   int k, count=0;
534   memory_word *eqtb = zeqtb;
535 /*  for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
536   for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
537     if (eqtb[k].cint != 0) {
538       if (count == 0) {
539         show_char('\n');
540         show_line("EQTB ", 0);
541       }
542       sprintf(log_line, "%d ", k);
543       show_line(log_line, 0);
544       if (count++ > 256) break;
545     }
546   }
547   if (count != 0) show_char('\n');
548 }
549 #endif
550
551 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
552
553 #define MAXSPLITS 3
554
555 /* ad hoc default minimum growth in memory realloc is 62% */
556 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
557 int percent_grow    = 62; /* default minimum growth in memory realloc is 62% */
558 int total_allocated = 0;  /* total memory allocated so far */
559 int ini_max_address = 0;  /* maximum address when starting */
560 int max_address     = 0;  /* maximum address seen in allocated memory */
561
562 /* see texd.h */
563
564 // DON'T USE THIS in DLL VERSION
565
566 #ifndef _WINDOWS
567 #ifdef HEAPWALK
568 unsigned int heapthreshold=0; /* smallest size block interested in ... */
569
570 unsigned int heap_dump (FILE *output, int verbose)
571 {
572   unsigned int total=0;
573   struct _heapinfo hinfo;
574   int heapstatus;
575   int end_block=0;
576   int n;
577
578   if (verbose) fprintf(output, "HEAP DUMP:\n");
579
580 /*  if ((n = _heapchk ()) != _HEAPOK) { */
581   n = _HEAPOK;
582 #ifdef SHOWHEAPERROR
583   n = _heapchk();
584 #endif
585   if (n != _HEAPOK) { 
586     fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
587 #ifdef SHOWHEAPERROR
588     fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
589 #endif
590   }
591   hinfo._pentry = NULL;
592   while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
593     if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
594 //      if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
595     }
596     end_block = (int) hinfo._pentry + hinfo._size;
597     if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
598     if (hinfo._size >= heapthreshold && verbose)
599     fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
600       (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
601         hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
602           end_block);
603   }
604   switch (heapstatus) {
605     case _HEAPEMPTY:
606       if (verbose) fprintf(output, "OK - empty heap\n");
607       break;
608     case _HEAPEND:
609       if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
610       break;
611     case _HEAPBADPTR:
612       fprintf(output, "ERROR - %s\n", "bad pointer to heap");
613       break;
614     case _HEAPBADBEGIN:
615       fprintf(output, "ERROR - %s\n", "bad start of heap");
616       break;
617     case _HEAPBADNODE:
618       fprintf(output, "ERROR - %s\n", "bad node in heap");
619       break;  
620   }
621   return total;
622 }
623 #endif
624 #endif
625
626 void show_maximums (FILE *output)
627 {
628 #ifdef HEAPWALK
629   unsigned heaptotal=0;           /* no longer used */
630   heaptotal = heap_dump(stdout, 0);      /* 94/Apr/3 */
631 #endif
632   sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address); 
633 //  if (output != NULL) fputs(log_line, output); // log file
634 //  else if (flag == 0) show_line(log_line, 0); // informative
635 //  else if (flag == 1) show_line(log_line, 1); // error
636   if (output == stderr) show_line(log_line, 1);
637   else if (output == stdout) show_line(log_line, 0);
638   else fputs(log_line, output);
639 }
640
641 /* our own version of realloc --- avoid supposed MicroSoft version bug */
642 /* also tries _expand first, which can avoid address growth ... */
643
644 #ifdef USEOUREALLOC 
645 void *ourrealloc (void *old, size_t new_size)
646 {
647   void * mnew;
648   size_t old_size, overlap;
649
650 /*  round up to nearest multiple of four bytes *//* avoid unlikely alignment */
651   if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
652
653   if (old == NULL) return malloc (new_size);  /* no old block - use malloc */
654
655   old_size = _msize (old);
656   if (old_size >= new_size && old_size < new_size + 4) return old;
657 /*  _heapmin(); */  /* release unused heap space to the system - no op ? */
658 #ifdef HEAPSHOW
659   if (trace_flag) {
660     show_line("BEFORE REALLOC: \n", 0);
661 #ifdef HEAPWALK
662     (void) heap_dump(stdout, 1);     /* debugging 96/Jan/18 */
663 #endif
664   }
665 #endif
666   mnew = _expand (old, new_size);      /* first try and expand in place */
667   if (mnew != NULL) {
668     if (trace_flag) {
669       sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
670         mnew, new_size, old, old_size);
671       show_line(log_line, 0);
672     }
673     return mnew;
674   }
675 /*  *********************************************************************** */
676 /*  do this if you want to call the real realloc next -  */
677   mnew = realloc (old, new_size);
678 #ifdef HEAPSHOW
679   if (trace_flag) {
680     show_line("AFTER REALLOC: \n", 0);
681 #ifdef HEAPWALK
682     (void) heap_dump(stdout, 1);     /* debugging 96/Jan/18 */
683 #endif
684   }
685 #endif
686   if (mnew != NULL) return mnew;
687 /*  we are screwed typically if we ever drop through here - no more space */
688 /*  *********************************************************************** */
689   mnew = malloc (new_size);          /* otherwise find new space */
690   if (mnew == NULL) return mnew;        /* if unable to allocate */
691   if (old_size < new_size) overlap = old_size;
692   else overlap = new_size;
693   memcpy (mnew, old, overlap);         /* copy old data to new area */
694   free(old);                  /* free the old area */
695   return mnew;
696 }
697 #endif
698
699 void memory_error (char *s, int n)
700 {
701   if (log_opened) {
702     fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
703     show_maximums(log_file);
704 #ifdef HEAPWALK
705     if (heap_flag) (void) heap_dump(log_file, 1);
706 #endif
707   }
708   sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
709   show_line(log_line, 1);
710   show_maximums(stderr);
711 #ifdef HEAPWALK
712   if (heap_flag) (void) heap_dump(stderr, 1);
713 #endif
714 /*  exit (1); */      /* 94/Jan/22 */
715 /*  return to let TeX do its thing (such as complain about runaway) */  
716 /*  don't set abort_flag here */
717 }
718
719 void trace_memory (char *s, int n)
720 {
721   sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
722   show_line(log_line, 0);
723 }
724
725 void update_statistics (int address, int size, int oldsize)
726 {
727   if (address + size > max_address) max_address = address + size;
728   total_allocated =  total_allocated + size - oldsize;
729 }
730
731 void probe_memory (void)
732 {
733   char *s;
734   s = (char *) malloc (4); /* get current top address */
735   free(s);
736   update_statistics ((int) s, 0, 0); /* show where we are */
737 }
738
739 void probe_show (void)
740 {
741   probe_memory();
742   show_maximums(stdout);
743 #ifdef HEAPWALK
744   if (heap_flag) (void) heap_dump(stdout, 1);
745 #endif
746 }
747
748 size_t roundup (size_t n)
749 {
750   if ((n % 4) == 0) return n;
751   else return ((n / 4) + 1) * 4;
752 }
753
754 #ifdef ALLOCATETRIES
755 /* using allocating hyphenation trie slows things down maybe 1%              */
756 /* but saves typically (270k - 55k) = 215k of memory                         */
757 /* NOTE: it's safe to allocate based on the trie_max read from fmt file      */
758 /* since hyphenation trie cannot be extended (after iniTeX)                  */
759 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
760 /*                                                                           */
761 /* NOTE: we don't ever reallocate these                                      */
762 /* returns -1 if it fails                                                    */
763
764 int allocate_tries (int trie_max)
765 {
766   int n, nl, no, nc;
767 /*  if (trie_max > trie_size) {
768     sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
769       trie_max, trie_size);
770       show_line(log_line, 1);
771     exit (1);
772   } */ /* ??? removed 1993/dec/17 */
773   if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
774 /*  important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
775   nl = (trie_max + 1) * sizeof(halfword);    /* trie_trl[trie_size + 1] */
776   no = (trie_max + 1) * sizeof(halfword);    /* trie_tro[trie_size + 1] */
777   nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
778   n = nl + no + nc;
779   if (trace_flag) trace_memory("hyphen trie", n);
780   trie_trl = (halfword *) malloc (roundup(nl));
781   trie_tro = (halfword *) malloc (roundup(no));
782   trie_trc = (quarterword *) malloc (roundup(nc));
783   if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL) {
784     memory_error("hyphen trie", n);
785     return -1;
786   }
787   if (trace_flag) {
788     sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
789     show_line(log_line, 0);
790   }
791   update_statistics ((int) trie_trl, nl, 0);
792   update_statistics ((int) trie_tro, no, 0);
793   update_statistics ((int) trie_trc, nc, 0);
794 /*  sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
795   trie_size = trie_max;           /* BUG FIX 98/Jan/5 */
796   if (trace_flag)
797     probe_show();     /* 94/Mar/25 */
798   return 0;               // success
799 }
800 #endif
801
802 #ifdef ALLOCATEHYPHEN
803 bool prime (int);       /* test function later in this file */
804
805 int current_prime = 0;         /* remember in case reallocated later */
806
807 /* we don't return an address here, since TWO memory regions allocated */
808 /* plus, we don't really reallocate, we FLUSH the old information totally */
809 /* returns -1 if it fails */
810
811 int realloc_hyphen (int hyphen_prime)
812 {
813   int n, nw, nl;
814   if (!prime(hyphen_prime)) {
815     sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime); 
816     show_line(log_line, 1);
817 //    exit (1);
818     return -1;
819   }
820 /*  need not/cannot preserve old contents when hyphen prime is changed */
821 /*  if (hyph_list != NULL) free(hyph_list); */
822 /*  if (hyph_word != NULL) free(hyph_word); */
823 /*  important + 1 since str_number hyph_word[hyphen_prime + 1]  in original etc. */
824   nw = (hyphen_prime + 1) * sizeof(str_number);
825   nl = (hyphen_prime + 1) * sizeof(halfword);
826   n = nw + nl;
827   if (trace_flag) trace_memory("hyphen exception", n);
828 /*  initially hyph_word will be NULL so this acts like malloc */
829 /*  hyph_word = (str_number *) malloc (nw); */
830   hyph_word = (str_number *) REALLOC (hyph_word, nw);  /* 94/Mar/24 */
831 /*  initially hyph_list will be NULL so this acts like malloc */
832 /*  hyph_list = (halfword *) malloc (nl); */
833   hyph_list = (halfword *) REALLOC (hyph_list, nl);   /* 94/Mar/24 */
834   if (hyph_word == NULL || hyph_list == NULL) {
835     memory_error("hyphen exception", n);
836     return -1;
837   }
838   if (trace_flag) {
839     sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
840     show_line(log_line, 0);
841   }
842 /*  cannot preserve old contents when hyphen prime is changed */
843 #ifdef USEMEMSET
844   memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
845 #else
846   for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0; 
847 #endif
848 #ifdef USEMEMSET
849   memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
850 #else
851   for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0; 
852 #endif
853   hyph_count = 0;   /* or use reset_hyphen() in itex.c */
854   if (current_prime != 0) {
855     update_statistics ((int) hyph_word, nw, 
856       (current_prime + 1) * sizeof(str_number));
857     update_statistics ((int) hyph_list, nl, 
858       (current_prime + 1) * sizeof(halfword));
859   }
860   else {
861     update_statistics ((int) hyph_word, nw, 0);
862     update_statistics ((int) hyph_list, nl, 0);
863   }
864   current_prime = hyphen_prime;
865   if (trace_flag)  probe_show();     /* 94/Mar/25 */
866   return 0;               // success
867 }
868 #endif
869
870 int current_mem_size=0;   /* current total words in main mem allocated -1 */
871
872 /* this gets called from itex.c when it figures out what mem_top is */
873 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
874 /* initial allocation only, may get expanded later */
875 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
876 /* returns NULL if it fails */
877
878 #ifdef ALLOCATEMAIN   
879 /* initial main memory alloc - mem_top */
880 memory_word *allocate_main_memory (int size)
881 {
882   int n;
883   
884 /*  Using -i *and* pre-loading format */ /* in this case get called twice */
885 /*  Get rid of initial blank memory again or use realloc ... */
886 /*  Could we avoid this by detecting presence of & before allocating ? */
887 /*  Also, if its already large enough, maybe we can avoid this ? */
888 /*  don't bother if current_mem_size == mem_max - mem_start ? */
889   if (mainmemory != NULL) {
890 /*    free(mainmemory); */
891 /*    mainmemory = NULL; */
892     if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
893 /*    if (mem_spec_flag)
894   show_line("Cannot change initial main memory size when format is read\n", 1);*/
895   } 
896
897   mem_top = mem_bot + size;
898 #ifdef ALLOCATEHIGH         /* NOT USED ANYMORE */
899   if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;  
900 #endif
901   mem_max = mem_top;
902 #ifdef ALLOCATELOW          /* NOT USED ANYMORE */
903   if (mem_extra_low != 0 && !is_initex)
904     mem_start = mem_bot - mem_extra_low;  /* increase main memory */
905 #endif
906   mem_start = 0;     /* bottom of memory allocated by system */
907 /*  mem_min = mem_start; */ /* bottom of area made available to TeX */
908   mem_min = 0;       /* bottom of area made available to TeX */
909   n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
910   if (trace_flag) trace_memory("main memory", n);
911 /*  mainmemory = (memory_word *) malloc (n); */  /* 94/March/24 */
912 /*  normally mainmemory == NULL here so acts like malloc ... */
913   mainmemory = (memory_word *) REALLOC (mainmemory, n);
914   if (mainmemory == NULL) {
915     memory_error("initial main memory", n);
916 //    exit (1);             /* serious error */
917     return NULL;
918   }
919   if (trace_flag) {
920     sprintf(log_line, "Address main memory == %d\n", mainmemory);
921     show_line(log_line, 0);
922   }
923   zzzaa = mainmemory;
924   if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start; 
925   if (trace_flag) {
926     sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
927     show_line(log_line, 0);
928   }
929   update_statistics ((int) mainmemory, n,
930     (current_mem_size + 1) * sizeof (memory_word));
931 /*  current_mem_size = (mem_max - mem_start + 1); */
932   current_mem_size = mem_max - mem_start;   /* total number of words - 1 */
933   if (trace_flag)  probe_show();     /* 94/Mar/25 */
934   return zzzaa;             /* same as zmem, mem 94/Jan/24 */
935 }
936 #endif  /* end of ALLOCATEMAIN */
937
938 #ifdef ALLOCATEMAIN
939 /* int firstallocation = 1; */
940
941 /* increase main memory allocation at low end and high end */
942 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
943 /* returns NULL if it fails */
944
945 memory_word *realloc_main (int losize, int hisize)
946 {  
947   int k, minsize;
948   int newsize = 0;        /* to quieten compiler */
949   int n = 0;          /* to quieten compiler */
950   memory_word * newmemory = NULL; /* to quieten compiler */
951
952 /*  if (losize == 0 && hisize > 0) runawayflag = 1;     
953   else runawayflag = 0; */ /* 94/Jan/22 */
954
955   if (trace_flag) {
956     sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
957     show_line(log_line, 0);
958   }
959   if (is_initex) {
960     show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
961     if (! knuth_flag) 
962       show_line("Please use `-m=...' on command line\n", 0);
963 //    abort_flag++;  // ???
964     return NULL;
965   }
966   if (trace_flag) {
967     sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
968     show_line(log_line, 0);
969   }
970   if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
971     memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
972 //    abort_flag++;  // ???
973     return NULL;
974   }
975 /*  first allocation should expand *both* lo and hi */
976   if (hisize == 0 && mem_end == mem_max) hisize = losize;
977   if (losize == 0 && mem_start == mem_min) losize = hisize;
978 /*  try and prevent excessive frequent reallocations */
979 /*  while avoiding over allocation by too much */
980   minsize = current_mem_size / 100 * percent_grow;
981   if (losize + hisize < minsize) {
982     if (losize > 0 && hisize > 0) {
983       losize = minsize / 2;
984       hisize = minsize / 2;
985     }
986     else if (losize > 0) losize = minsize;
987     else if (hisize > 0) hisize = minsize;
988   }
989   if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
990   if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
991
992   for (k = 0; k < MAXSPLITS; k++) {
993     newsize = current_mem_size + losize + hisize;
994     if (newsize >= max_mem_size) {    /* bump against limit - ha ha ha */
995       while (newsize >= max_mem_size) {
996         losize = losize / 2; hisize = hisize / 2;
997         newsize = current_mem_size + losize + hisize;
998       }
999     }
1000     n = (newsize + 1) * sizeof (memory_word);
1001     if (trace_flag) trace_memory("main memory", n);
1002     newmemory = (memory_word *) REALLOC (mainmemory, n);
1003     if (newmemory != NULL) break; /* did we get it ? */
1004     if (current_mem_size == 0) break; /* in case we ever use for initial */
1005     losize = losize / 2; hisize = hisize / 2;
1006   }
1007
1008   if (newmemory == NULL) {
1009     memory_error("main memory", n);
1010     return zzzaa;           /* try and continue with TeX !!! */
1011   }
1012   if (trace_flag) {
1013     sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1014     show_line(log_line, 0);
1015   }
1016   if (losize > 0) {
1017 /*  shift everything upward to make space for new low area */
1018     if (trace_flag) {
1019       sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1020           newmemory, (current_mem_size + 1) * sizeof(memory_word));
1021       show_line(log_line, 0);
1022     }
1023     memmove (newmemory + losize, newmemory, 
1024 /*      current_mem_size * sizeof(memory_word));  */
1025       (current_mem_size + 1) * sizeof(memory_word));
1026 /*  could reduce words moved by (mem_max - mem_end) */
1027   }
1028   mainmemory = newmemory;       /* remember for free later */
1029   if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1030   if (hisize > 0) mem_max = mem_max + hisize;   /* update upper limit */
1031   update_statistics ((int) mainmemory, n,
1032     (current_mem_size + 1) * sizeof (memory_word));
1033   current_mem_size = newsize;
1034   if (current_mem_size != mem_max - mem_start) {
1035     show_line("ERROR: Impossible Memory Error\n", 1);
1036   }
1037   if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1038   else zzzaa = mainmemory;
1039   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1040   return zzzaa;
1041 }
1042 #endif
1043
1044 #ifdef ALLOCATEFONT
1045 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1046
1047 int current_font_mem_size=0;
1048
1049 /* fmemoryword can be either halfword or memory_word */
1050 fmemoryword *realloc_font_info (int size)
1051 { /* number of memorywords */
1052   fmemoryword *newfontinfo=NULL;
1053   int k, minsize;
1054   int newsize=0;        /* to quieten compiler */
1055   int n=0;          /* to quieten compiler */
1056
1057   if (trace_flag) {
1058     sprintf(log_line, "Old Address %s == %d\n",  "font_info", font_info);
1059     show_line(log_line, 0);
1060   }
1061 /*  during initial allocation, font_info == NULL - realloc acts like malloc */
1062 /*  during initial allocation current_font_mem_size == 0 */
1063   if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1064 /*    memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1065     return font_info;    /* pass it back to TeX 99/Fabe/4 */
1066   }
1067 /*  try and prevent excessive frequent reallocations */
1068 /*  while avoiding over allocation by too much */
1069 /*  minsize = current_font_mem_size / 2; */
1070   minsize = current_font_mem_size / 100 * percent_grow;
1071   if (size < minsize) size = minsize;
1072   if (size < initial_font_mem_size) size = initial_font_mem_size;
1073
1074   for (k=0; k < MAXSPLITS; k++) {
1075     newsize = current_font_mem_size + size;
1076     if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1077 /*    important + 1 since fmemoryword font_info[font_mem_size + 1]  original */
1078     n = (newsize + 1) * sizeof (fmemoryword);
1079     if (trace_flag) trace_memory("font_info", n);
1080     newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1081     if (newfontinfo != NULL) break;   /* did we get it ? */
1082     if (current_font_mem_size == 0) break; /* initial allocation must work */
1083     size = size / 2;
1084   }
1085
1086   if (newfontinfo == NULL) {
1087     memory_error("font", n);
1088     return font_info;        /* try and continue !!! */
1089   }
1090   font_info = newfontinfo;
1091   if (trace_flag) {
1092     sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1093     show_line(log_line, 0);
1094   }
1095   update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1096   current_font_mem_size = newsize;
1097   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1098   return font_info;
1099 }
1100 #endif
1101
1102 #ifdef ALLOCATESTRING
1103 int current_pool_size=0;
1104
1105 packed_ASCII_code *realloc_str_pool (int size)
1106 {
1107   int k, minsize;
1108   int newsize=0;
1109   int n=0;
1110   packed_ASCII_code *newstrpool=NULL;
1111
1112   if (trace_flag) {
1113     sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1114     show_line(log_line, 0);
1115   }
1116   if (current_pool_size == pool_size) {
1117 /*    memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1118 /*    exit (1); */
1119     return str_pool;   /* pass it back to TeX 99/Fabe/4 */
1120   }
1121 /*  minsize =  current_pool_size / 2; */
1122   minsize =  current_pool_size / 100 * percent_grow;
1123   if (size < minsize) size = minsize;
1124   if (size < initial_pool_size) size = initial_pool_size;
1125
1126   for (k = 0; k < MAXSPLITS; k++) {
1127     newsize = current_pool_size + size;
1128     if (newsize > pool_size) newsize = pool_size;
1129 /* important + 1 since  packed_ASCII_code str_pool[pool_size + 1]; in original */
1130     n = (newsize + 1) * sizeof (packed_ASCII_code);
1131     if (trace_flag) trace_memory("str_pool", n);
1132     newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1133     if (newstrpool != NULL) break;    /* did we get it ? */
1134     if (current_pool_size == 0) break;  /* initial allocation must work */
1135     size = size / 2;          /* else can retry smaller */
1136   }
1137
1138   if (newstrpool == NULL) {
1139     memory_error("string pool", n);
1140     return str_pool;           /* try and continue !!! */
1141   }
1142   str_pool = newstrpool;
1143   update_statistics ((int) str_pool, n, current_pool_size);
1144   current_pool_size = newsize;
1145   if (trace_flag) {
1146     sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1147     show_line(log_line, 0);
1148   }
1149   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1150   return str_pool;
1151 }
1152 #endif
1153
1154 #ifdef ALLOCATESTRING
1155 int current_max_strings=0;
1156
1157 pool_pointer *realloc_str_start (int size)
1158 {
1159   int k, minsize;
1160   int n=0;
1161   int newsize=0;
1162   pool_pointer *newstrstart=NULL;
1163
1164   if (trace_flag) {
1165     sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1166     show_line(log_line, 0);
1167   }
1168   if (current_max_strings == max_strings) {
1169 /*    memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1170 /*    exit (1); */
1171     return str_start;    /* pass it back to TeX 99/Fabe/4 */
1172   }
1173 /*  minsize = current_max_strings / 2; */
1174   minsize = current_max_strings / 100 * percent_grow;
1175   if (size < minsize) size = minsize;
1176   if (size < initial_max_strings) size = initial_max_strings;
1177
1178   for (k = 0; k < MAXSPLITS; k++) {
1179     newsize = current_max_strings + size;
1180     if (newsize > max_strings) newsize = max_strings;
1181 /*    important + 1 since str_start[maxstring + 1] originally */
1182     n = (newsize + 1) * sizeof (pool_pointer); 
1183     if (trace_flag) trace_memory("str_start", n);
1184     newstrstart = (pool_pointer *) REALLOC (str_start, n);
1185     if (newstrstart != NULL) break;   /* did we get it ? */
1186     if (current_max_strings == 0) break;  /* initial allocation must work */
1187     size = size / 2;          /* otherwise can try smaller */
1188   }
1189
1190   if (newstrstart == NULL) {
1191     memory_error("string pointer", n);
1192     return str_start;          /* try and continue */
1193   }
1194   str_start = newstrstart;
1195   update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1196   current_max_strings = newsize;
1197   if (trace_flag) {
1198     sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1199     show_line(log_line, 0);
1200   }
1201   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1202   return str_start;
1203 }
1204 #endif
1205
1206 #ifdef ALLOCATEINI
1207
1208 /* returns -1 if it fails */
1209
1210 int allocate_ini (int size)
1211 {    /* size == trie_size */
1212   int n, nl, no, nc, nr, nh, nt;
1213     nh = nr = nl = (size + 1) *  sizeof(trie_pointer);
1214     no = (size + 1) *  sizeof(trie_op_code);
1215     nc = (size + 1) *  sizeof(packed_ASCII_code);
1216 /*    nt = (size + 1) *  sizeof(bool); */
1217     nt = (size + 1) *  sizeof(char);
1218     n = nl + no + nc + nr + nh + nt;
1219 /*    n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1220       3 *  sizeof(trie_pointer) + sizeof (char)); */
1221     if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1222     trie_l = (trie_pointer *) malloc (roundup(nl));
1223     trie_o = (trie_op_code *) malloc (roundup(no));
1224     trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1225     trie_r = (trie_pointer *) malloc (roundup(nr));
1226     trie_hash = (trie_pointer *) malloc (roundup(nh));
1227 /*    trie_taken = (bool *) malloc (nt); */
1228     trie_taken = (char *) malloc (roundup(nt));
1229     if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1230       trie_hash == NULL || trie_taken == NULL) {
1231       memory_error("iniTeX hyphen trie", n);
1232 //      exit (1);           /* serious error */     
1233       return -1;
1234     }
1235     if (trace_flag) {
1236       sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n", 
1237           trie_l, trie_o, trie_c);
1238       show_line(log_line, 0);
1239       sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n", 
1240           trie_r, trie_hash, trie_taken);
1241       show_line(log_line, 0);
1242     }
1243     update_statistics ((int) trie_l, nl, 0);
1244     update_statistics ((int) trie_o, no, 0);
1245     update_statistics ((int) trie_c, nc, 0);
1246     update_statistics ((int) trie_r, nr, 0);
1247     update_statistics ((int) trie_hash, nh, 0);
1248     update_statistics ((int) trie_taken, nt, 0);
1249 /*    trie_size = size; */ /* ??? */
1250     if (trace_flag)  probe_show();     /* 94/Mar/25 */
1251     return 0;               // success
1252 }
1253 #endif
1254
1255 #ifdef ALLOCATESAVESTACK
1256 int current_save_size=0;
1257
1258 memory_word *realloc_save_stack (int size)
1259 {
1260   int k, minsize;
1261   int n=0, newsize=0;
1262   memory_word *newsave_stack=NULL;
1263
1264   if (trace_flag) {
1265     sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1266     show_line(log_line, 0);
1267   }
1268   if (current_save_size == save_size) {  /* arbitrary limit */
1269 /*    memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1270 /*    exit (1); */
1271     return save_stack;       /* let TeX handle the error */
1272   }
1273   minsize =  current_save_size / 100 * percent_grow;
1274   if (size < minsize) size = minsize;
1275   if (size < initial_save_size) size = initial_save_size;
1276
1277   for (k = 0; k < MAXSPLITS; k++) {
1278     newsize = current_save_size + size;
1279     if (newsize > save_size) newsize = save_size;
1280     n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1281     if (trace_flag) trace_memory("save_stack", n);
1282     newsave_stack = (memory_word *) REALLOC (save_stack, n);
1283     if (newsave_stack != NULL) break;    /* did we get it ? */
1284     if (current_save_size == 0) break;  /* initial allocation must work */
1285     size = size / 2;          /* else can retry smaller */
1286   }
1287
1288   if (newsave_stack == NULL) {
1289     memory_error("save stack", n);
1290     return save_stack;           /* try and continue !!! */
1291   }
1292   save_stack = newsave_stack;
1293   update_statistics ((int) save_stack, n, current_save_size);
1294   current_save_size = newsize;
1295   if (trace_flag) {
1296     sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1297     show_line(log_line, 0);
1298     sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1299     show_line(log_line, 0);
1300   }
1301   if (trace_flag) probe_show();      /* 94/Mar/25 */
1302   return save_stack;
1303 }
1304 #endif
1305
1306 #ifdef ALLOCATEINPUTSTACK
1307 int current_stack_size=0;       /* input stack size */
1308
1309 in_state_record *realloc_input_stack (int size)
1310 {
1311   int k, minsize;
1312   int n=0, newsize=0;
1313   in_state_record *newinputstack=NULL;
1314
1315   if (trace_flag) {
1316     sprintf(log_line, "Old Address %s == %d\n",  "input stack", input_stack);
1317     show_line(log_line, 0);
1318   }
1319   if (current_stack_size == stack_size) {  /* arbitrary limit */
1320 /*    memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1321 /*    exit (1); */
1322     return input_stack;
1323   }
1324   minsize =  current_stack_size / 100 * percent_grow;
1325   if (size < minsize) size = minsize;
1326   if (size < initial_stack_size) size = initial_stack_size;
1327
1328   for (k = 0; k < MAXSPLITS; k++) {
1329     newsize = current_stack_size + size;
1330     if (newsize > stack_size) newsize = stack_size;
1331     n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1332     if (trace_flag) trace_memory("input_stack", n);
1333     newinputstack = (in_state_record *) REALLOC (input_stack, n);
1334     if (newinputstack != NULL) break;   /* did we get it ? */
1335     if (current_stack_size == 0) break; /* initial allocation must work */
1336     size = size / 2;          /* else can retry smaller */
1337   }
1338
1339   if (newinputstack == NULL) {
1340     memory_error("input stack", n);
1341     return input_stack;            /* try and continue !!! */
1342   }
1343   input_stack = newinputstack;
1344   update_statistics ((int) input_stack, n, current_stack_size);
1345   current_stack_size = newsize;
1346   if (trace_flag) {
1347     sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1348     show_line(log_line, 0);
1349     sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1350     show_line(log_line, 0);
1351   }
1352   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1353   return input_stack;
1354 }
1355 #endif
1356
1357 #ifdef ALLOCATENESTSTACK
1358 int current_nest_size=0;        /* current nest size */
1359
1360 list_state_record *realloc_nest_stack (int size)
1361 {
1362   int k, minsize;
1363   int n=0, newsize=0;
1364   list_state_record *newnest=NULL;
1365
1366   if (trace_flag) {
1367     sprintf(log_line, "Old Address %s == %d\n",  "nest stack", nest);
1368     show_line(log_line, 0);
1369   }
1370   if (current_nest_size == nest_size) {  /* arbitrary limit */
1371 /*    memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1372 /*    exit (1); */
1373     return nest;        /* let TeX handle the error */
1374   }
1375   minsize =  current_nest_size / 100 * percent_grow;
1376   if (size < minsize) size = minsize;
1377   if (size < initial_nest_size) size = initial_nest_size;
1378
1379   for (k = 0; k < MAXSPLITS; k++) {
1380     newsize = current_nest_size + size;
1381     if (newsize > nest_size) newsize = nest_size;
1382     n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1383     if (trace_flag) trace_memory("nest stack", n);
1384     newnest = (list_state_record *) REALLOC (nest, n);
1385     if (newnest != NULL) break;   /* did we get it ? */
1386     if (current_nest_size == 0) break;  /* initial allocation must work */
1387     size = size / 2;          /* else can retry smaller */
1388   }
1389
1390   if (newnest == NULL) {
1391     memory_error("nest stack", n);
1392     return nest;            /* try and continue !!! */
1393   }
1394   nest = newnest;
1395   update_statistics ((int) nest, n, current_nest_size);
1396   current_nest_size = newsize;
1397   if (trace_flag) {
1398     sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1399     show_line(log_line, 0);
1400     sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1401     show_line(log_line, 0);
1402   }
1403   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1404   return nest;
1405 }
1406 #endif
1407
1408 #ifdef ALLOCATEPARAMSTACK
1409 int current_param_size=0;       /* current param size */
1410
1411 halfword *realloc_param_stack (int size)
1412 {
1413   int k, minsize;
1414   int n=0, newsize=0;
1415   halfword *newparam=NULL;
1416
1417   if (trace_flag) {
1418     sprintf(log_line, "Old Address %s == %d\n",  "param stack", param_stack);
1419     show_line(log_line, 0);
1420   }
1421   if (current_param_size == param_size) {  /* arbitrary limit */
1422 /*    memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1423 /*    exit (1); */
1424     return param_stack;        /* let TeX handle the error */
1425   }
1426   minsize =  current_param_size / 100 * percent_grow;
1427   if (size < minsize) size = minsize;
1428   if (size < initial_param_size) size = initial_param_size;
1429
1430   for (k = 0; k < MAXSPLITS; k++) {
1431     newsize = current_param_size + size;
1432     if (newsize > param_size) newsize = param_size;
1433     n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1434     if (trace_flag) trace_memory("param stack", n);
1435     newparam = (halfword *) REALLOC (param_stack, n); 
1436     if (newparam != NULL) break;    /* did we get it ? */
1437     if (current_param_size == 0) break; /* initial allocation must work */
1438     size = size / 2;          /* else can retry smaller */
1439   }
1440
1441   if (newparam == NULL) {
1442     memory_error("param stack", n);
1443     return param_stack;            /* try and continue !!! */
1444   }
1445   param_stack = newparam;
1446   update_statistics ((int) param_stack, n, current_param_size);
1447   current_param_size = newsize;
1448   if (trace_flag) {
1449     sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1450     show_line(log_line, 0);
1451     sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1452     show_line(log_line, 0);
1453   }
1454   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1455   return param_stack;
1456 }
1457 #endif
1458
1459 #ifdef ALLOCATEBUFFER
1460 int current_buf_size=0;
1461
1462 ASCII_code *realloc_buffer (int size)
1463 {
1464   int k, minsize;
1465   int n=0, newsize=0;
1466   ASCII_code *newbuffer=NULL;
1467
1468   if (trace_flag) {
1469     sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1470     show_line(log_line, 0);
1471   }
1472   if (current_buf_size == buf_size) {  /* arbitrary limit */
1473 /*    memory_error ("buffer", buf_size); */
1474 /*    exit (1); */
1475     return buffer;    /* pass it back to TeX 99/Fabe/4 */
1476   }
1477   minsize =  current_buf_size / 100 * percent_grow;
1478   if (size < minsize) size = minsize;
1479   if (size < initial_buf_size) size = initial_buf_size;
1480
1481   for (k = 0; k < MAXSPLITS; k++) {
1482     newsize = current_buf_size + size;
1483     if (newsize > buf_size) newsize = buf_size;
1484     n = (newsize + 1) * sizeof(ASCII_code);  /* buffer[buf_size + 1] */
1485     if (trace_flag) trace_memory("buffer", n);
1486     newbuffer = (ASCII_code *) REALLOC (buffer, n);
1487     if (newbuffer != NULL) break;   /* did we get it ? */
1488     if (current_buf_size == 0) break;   /* initial allocation must work */
1489     size = size / 2;          /* else can retry smaller */
1490   }
1491
1492   if (newbuffer == NULL) {
1493     memory_error("buffer", n);
1494     return buffer;            /* try and continue !!! */
1495   }
1496   buffer = newbuffer;
1497   update_statistics ((int) buffer, n, current_buf_size);
1498 #ifdef USEMEMSET
1499   memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1500 #else
1501   for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1502 #endif
1503   current_buf_size = newsize;
1504   if (trace_flag) {
1505     sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1506     show_line(log_line, 0);
1507     sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1508     show_line(log_line, 0);
1509   }
1510   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1511   return buffer;
1512 }
1513 #endif
1514
1515 /* we used to allocate this one only to reduce the size of the PE file */
1516 /* not used anymore - NO advantage */
1517
1518 #ifdef ALLOCATEDVIBUF
1519 eight_bits *allocatedvibuf (int size)
1520 {
1521   eight_bits *dvi_buf;
1522   int n;
1523
1524   n = (size + 1) * sizeof(eight_bits);
1525   if (trace_flag) trace_memory("dvi_buf", n);
1526   dvi_buf = (eight_bits *) malloc (roundup(n));
1527   if (dvi_buf == NULL) {
1528     memory_error("dvi_buf", n);
1529     return NULL;
1530   }
1531   if (trace_flag) {
1532     sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1533     show_line(log_line, 0);
1534   }
1535   update_statistics ((int) dvi_buf, n, 0);
1536   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1537   return dvi_buf;
1538 }
1539 #endif
1540
1541 /* we used to allocate this one only to reduce the size of the PE file */
1542 /* it can be done without loss in performance, since register eqtb = zeqtb */
1543 #ifdef ALLOCATEZEQTB
1544 memory_word *allocatezeqtb (int k)
1545 {
1546   memory_word *zeqtb;
1547   int n;
1548
1549   n = k * sizeof (memory_word);  /* 13507 * 8 = 108 kilobytes */
1550   if (trace_flag)  trace_memory("eqtb", n);
1551   zeqtb = (memory_word *) malloc (roundup(n));
1552   if (zeqtb == NULL)  {
1553     memory_error("eqtb", n);
1554 //    exit (1);           /* serious error */   
1555     return NULL;
1556   }
1557   if (trace_flag) {
1558     sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1559     show_line(log_line, 0);
1560   }
1561   update_statistics ((int) zeqtb, n, 0);
1562   if (trace_flag)  probe_show();     /* 94/Mar/25 */
1563   return zeqtb;
1564 }
1565 #endif
1566
1567 /* here is the main memory allocation routine -- calls the above */
1568 /* returns -1 if it fails */
1569
1570 int allocate_memory (void)
1571 { /* allocate rather than static 93/Nov/26 */
1572 /*  int n;  */
1573 #ifdef PREALLOCHOLE
1574   char *holeadr = malloc (300000);  /* testing - preallocate 95/Jan/20 */
1575 #endif
1576
1577 #ifdef ALLOCATEHASH
1578 #error ERROR: Not ready for ALLOCATEHASH...
1579 #endif
1580
1581 /* probably not worth while/not a good idea allocating following */
1582 /* they are all rather small, and typically don't need expansion */
1583 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1584 #ifdef ALLOCATEHASH
1585 /*  n = 9767 * sizeof (twohalves);  *//* 60 kilo bytes */   
1586 /*  n = (hash_size + 267) * sizeof (twohalves); */  /* 60 kilo bytes */
1587 /*  n = (9767 + eqtb_extra) * sizeof (twohalves); */
1588 #ifdef SHORTHASH
1589   n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves);   /* 95/Feb/19 */
1590 #else
1591   n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves);  /* 95/Feb/19 */
1592 #endif
1593   if (trace_flag)  trace_memory("hash table", n);
1594 #ifdef SHORTHASH
1595   zzzae = (htwohalves *) malloc (roundup(n));
1596 #else
1597   zzzae = (twohalves *) malloc (roundup(n));
1598 #endif
1599 /*  zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1600   if (zzzae == NULL)  {
1601     memory_error("hash table", n);
1602 //    exit (1);           /* serious error */
1603     return -1;            /* serious error */
1604   }
1605
1606   n = (inputsize + 1) * sizeof(memory_word);
1607   if (trace_flag)  trace_memory("input_stack", n);
1608 /*  input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1609   input_stack = (memory_word *) malloc (roundup(n));
1610   if (input_stack == NULL)   {
1611     memory_error("input_stack", n);
1612 //    exit (1);           /* serious error */
1613     return -1;            /* serious error */
1614   }
1615 #endif
1616
1617 /* no real reason to allocate dvi_buf - no need to ever grow it */
1618 #ifdef ALLOCATEDVIBUF
1619 /*  zdvibuf = NULL; */
1620   zdvibuf = allocatedvibuf (dvi_buf_size);
1621   if (zdvibuf == NULL) return -1;
1622 #endif
1623
1624 #ifdef ALLOCATEZEQTB
1625 /*  zeqtb = NULL; */
1626 #ifdef INCREASEFONTS
1627 /*  zeqtb = allocatezeqtb (13507 + eqtb_extra); */  /* 94/Mar/29 */
1628   zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra);  /* 94/Mar/29 */
1629 #else
1630 /*  zeqtb = allocatezeqtb (13507); */
1631   zeqtb = allocatezeqtb (hash_size + 4007); 
1632 #endif
1633 #endif
1634
1635 #ifdef ALLOCATEINPUTSTACK
1636   input_stack = NULL;        /* new 1999/Jan/21 */
1637   current_stack_size = 0;
1638   input_stack = realloc_input_stack (initial_stack_size);  /* + 1 */
1639 #endif
1640
1641 #ifdef ALLOCATENESTSTACK
1642   nest = NULL;          /* new 1999/Jan/21 */
1643   current_nest_size = 0;
1644   nest = realloc_nest_stack (initial_nest_size);  /* + 1 */
1645 #endif
1646
1647 #ifdef ALLOCATEPARAMSTACK
1648   param_stack = NULL;          /* new 1999/Jan/21 */
1649   current_param_size = 0;
1650   param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1651 #endif
1652
1653 #ifdef ALLOCATESAVESTACK
1654   save_stack = NULL;       /* new 1999/Jan/7 */
1655   current_save_size = 0;
1656   save_stack = realloc_save_stack (initial_save_size);
1657 #endif
1658
1659 #ifdef IGNORED
1660   buffer = NULL;        /* need to do earlier */
1661   current_buf_size = 0;
1662   buffer = realloc_buffer (initial_buf_size);
1663 #endif
1664
1665 #ifdef ALLOCATESTRING
1666   str_pool = NULL;
1667   current_pool_size = 0;
1668   str_start = NULL;
1669   current_max_strings = 0;
1670 /*  need to create space because iniTeX writes in before reading pool file */
1671 /*  for a start, puts in strings for 256 characters */
1672 /*  maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1673   if (is_initex) {
1674     if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1675     str_pool = realloc_str_pool (initial_pool_size); 
1676     str_start = realloc_str_start (initial_max_strings);
1677   }
1678 #endif
1679
1680 /* the following can save a lot of the usual 800k fixed allocation */
1681 #ifdef ALLOCATEFONT
1682   font_info = NULL;
1683   current_font_mem_size = 0;
1684 /*  if not iniTeX, then do initial allocation on fmt file read in itex.c */
1685 /*  if ini-TeX we need to do it here - no format file read later */
1686   if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1687 #endif
1688     
1689 #ifdef ALLOCATEMAIN
1690   mainmemory = NULL;
1691   zzzaa = NULL;
1692   mem_min = mem_bot;        /* just to avoid complaints in texbody */
1693   mem_top = mem_initex;
1694   mem_max = mem_top;
1695 /*  allocate main memory here if this is iniTeX */
1696 /*  otherwise wait for format undumping in itex.c ... */  
1697   if (is_initex) {
1698 /*    avoid this if format specified on command line ??? */
1699 /*    allocate_main_memory(mem_initex); */   /* made variable ! */
1700     mem = allocate_main_memory(mem_initex);  /* made variable ! */
1701     if (mem == NULL)
1702 //      exit (1);
1703       return -1;            /* serious error */
1704   }
1705 #endif
1706
1707 /* now for the hyphenation exception stuff */
1708 #ifdef ALLOCATEHYPHEN
1709   hyph_word = NULL;
1710   hyph_list = NULL;
1711 /*  this will be overridden later by what is in format file */
1712   hyphen_prime = default_hyphen_prime;
1713 /*  non ini-TeX use assumes format will be read and that specifies size */
1714   if (is_initex) {
1715     if (new_hyphen_prime) hyphen_prime = new_hyphen_prime;
1716     if (realloc_hyphen (hyphen_prime)) /* allocate just in case no format */
1717       return -1;
1718   }
1719 #endif
1720
1721 /*  now for memory for the part of the hyphenation stuff that always needed */
1722 /*  if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1723 /*  if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1724 #ifdef ALLOCATETRIES
1725   if (is_initex) {
1726     if (allocate_tries (trie_size)) return -1;
1727   }
1728 #endif
1729
1730 /*  now for memory for hyphenation stuff needed only when running iniTeX */
1731 #ifdef ALLOCATEINI
1732   if (is_initex) {
1733     if (allocate_ini(trie_size)) return -1;
1734   }
1735   else {
1736     trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1737     trie_c = NULL;       /* (trie_size + 1) * char */
1738     trie_taken = NULL;     /* (trie_size + 1) * bool */
1739   }
1740 #endif
1741 #ifdef PREALLOCHOLE
1742   free(holeadr);          /* create the hole */
1743 #endif
1744   return 0;           // success
1745 }
1746
1747 /* returns non-zero if error - done to test integrity of stack mostly */
1748
1749 int free_memory (void)
1750 {     /* free in reverse order 93/Nov/26 */
1751   int n;
1752   unsigned heaptotal=0;
1753 /*  unsigned total; */
1754
1755   if (trace_flag) show_line("free_memory ", 0);
1756
1757 #ifdef CHECKEQTB
1758   if (debug_flag) check_eqtb("free_memory");
1759 #endif
1760   if (verbose_flag || trace_flag) show_maximums(stdout); 
1761 #ifdef HEAPWALK
1762   if (heap_flag) (void) heap_dump(stdout, 1);
1763 #endif
1764   if (trace_flag) {
1765 #ifdef HEAPWALK
1766     heaptotal = (void) heap_dump(stdout, 0);
1767 #endif
1768     sprintf(log_line, "Heap total: %u bytes --- max address %u\n", 
1769         heaptotal, max_address);
1770     show_line(log_line, 0);
1771   }
1772   if (trace_flag) {
1773     sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1774       lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end  - hi_mem_min, hi_mem_min, mem_end);
1775     show_line(log_line, 0);
1776   }
1777 /*  following only needed to check consistency of heap ... useful debugging */
1778   if (trace_flag) show_line("Freeing memory again\n", 0);
1779
1780 /*  if (trace_flag)
1781     show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1782
1783 /*  the following checks the heap integrity */
1784
1785 /*  if ((n = _heapchk ()) != _HEAPOK) { */      /* 94/Feb/18 */
1786   n = _HEAPOK;
1787 #ifdef SHOWHEAPERROR
1788   n = _heapchk();
1789   if (n != _HEAPOK) {     /* 94/Feb/18 */
1790     sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1791     show_line(log_line, 1);
1792     sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1793     show_line(log_line, 0);
1794     return n;   /* non-zero and negative */ /* unreachable ??? */
1795   }
1796 #endif
1797 /*  only free memory if safe ... additional check */
1798 #ifdef ALLOCATEINI
1799   if (is_initex) {
1800     if (trie_taken != NULL) free(trie_taken);
1801     if (trie_hash  != NULL) free(trie_hash);
1802     if (trie_r     != NULL) free(trie_r);
1803     if (trie_c     != NULL) free(trie_c);
1804     if (trie_o     != NULL) free(trie_o);
1805     if (trie_l     != NULL) free(trie_l);
1806     trie_taken = NULL;
1807     trie_hash = trie_l = trie_r = NULL;
1808     trie_c = NULL;
1809     trie_o = NULL;
1810   }
1811 #endif  
1812 #ifdef ALLOCATETRIES
1813   if (trie_trc != NULL) free (trie_trc);
1814   if (trie_tro != NULL) free (trie_tro);
1815   if (trie_trl != NULL) free (trie_trl);
1816   trie_trc = NULL;
1817   trie_tro = trie_trl = NULL;
1818 #endif
1819 #ifdef ALLOCATEHYPHEN
1820   if (hyph_list != NULL) free(hyph_list);
1821   if (hyph_word != NULL) free(hyph_word);
1822   hyph_list = NULL;
1823   hyph_word = NULL;
1824 #endif
1825 #ifdef ALLOCATEMAIN
1826 /*  if (zzzaa != NULL) free(zzzaa); */  /* NO: zzzaa may be offset ! */
1827   if (mainmemory != NULL) free(mainmemory);
1828   mainmemory = NULL;
1829 #endif
1830 #ifdef ALLOCATEFONT
1831   if (font_info != NULL) free(font_info);
1832   font_info = NULL;
1833 #endif
1834 #ifdef ALLOCATESTRING
1835   if (str_start != NULL) free(str_start);
1836   if (str_pool != NULL) free(str_pool);
1837   str_start = NULL;
1838   str_pool = NULL;
1839 #endif
1840
1841 #ifdef ALLOCATEHASH
1842   if (zzzae != NULL) free(zzzae);
1843   zzzae = NULL;
1844 #endif
1845
1846 #ifdef ALLOCATEDVIBUF
1847   if (zdvibuf != NULL) free(zdvibuf);
1848   zdvibuf = NULL;
1849 #endif
1850 #ifdef ALLOCATEZEQTB
1851   if (zeqtb != NULL) free(zeqtb);
1852   zeqtb = NULL;
1853 #endif
1854
1855 #ifdef ALLOCATEPARAMSTACK
1856   if (param_stack != NULL) free(param_stack);
1857   param_stack = NULL;
1858 #endif
1859 #ifdef ALLOCATENESTSTACK
1860   if (nest != NULL) free(nest);
1861   nest = NULL;
1862 #endif
1863 #ifdef ALLOCATEINPUTSTACK
1864   if (input_stack != NULL) free(input_stack);
1865   input_stack = NULL;
1866 #endif
1867 #ifdef ALLOCATESAVESTACK
1868   if (save_stack != NULL) free(save_stack);
1869   save_stack = NULL;
1870 #endif
1871 /*  if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1872   if (format_file != NULL) free(format_file);   /* 96/Jan/16 */
1873   if (string_file != NULL) free(string_file);   /* 96/Jan/16 */
1874   if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1875   format_file = string_file = source_direct = NULL;
1876   if (dvi_file_name != NULL) free(dvi_file_name);
1877   if (log_file_name != NULL) free(log_file_name);
1878   log_file_name = dvi_file_name = NULL;       /* 00/Jun/18 */
1879   return 0;
1880 }
1881
1882 bool prime (int x)
1883 {
1884   int k;
1885   int sum = 1;    /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1886   if (x % 2 == 0) return false;
1887   for (k = 3; k < x; k = k + 2) {
1888     if (x % k == 0) return false;
1889 /*    if (k * k > x) return true; */
1890     if (sum * 4 > x) return true;
1891     sum += k;
1892   }
1893   return true;
1894 }
1895
1896 int quitflag=0;
1897 bool show_use=false;
1898 bool floating=false;
1899
1900 void complainarg (int c, char *s)
1901 {
1902   sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1903   show_line(log_line, 1);
1904   show_use = 1;           // 2000 June 21
1905 }
1906
1907 /* following is list of allowed command line flags and args */
1908
1909 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1910
1911 /* only  01234567.9 still left to take ... maybe recycle u */
1912
1913 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1914
1915 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1916
1917 void reorderargs (int ac, char **av)
1918 {      /* put in 1993/Dec/28 */
1919   int n, m;
1920   char *s, *t;
1921 //  char takeargs[128];   /* large enough for all command line arg chars */
1922   char takeargs[256];   /* large enough for all command line arg chars */
1923
1924 /*  assumes arg pointers av[] are writeable */
1925 /*  for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1926
1927   if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1928 /*    show_line("No arguments?\n", 0); */  /* debugging */
1929     return;             /* no args ! */
1930   }
1931
1932   s = allowedargs;
1933   t = takeargs;   /* list of those that take args */
1934   while (*s != '\0' && *(s+1) != '\0') {
1935     if (*(s+1) == '=') *t++ = *s++;   /* copy over --- without the = */
1936     s++;
1937   }
1938   *t = '\0';
1939   if (trace_flag) {
1940     show_line(takeargs, 0);
1941     show_char('\n');
1942   }
1943   
1944   n = 1;
1945   for (;;) {              /* scan to end of command line args */
1946     if (*av[n] != '-') break;
1947 /*    does it take an argument ? and is this argument next ? */
1948     if (n+1 < ac &&
1949       *(av[n]+2) == '\0' &&
1950 /*        strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1951         strchr(takeargs, *(av[n]+1)) != NULL)
1952           n += 2; /* step over it */
1953     else n++;
1954     if (n == ac) break;
1955   }
1956
1957   for (;;) {              /* look for more command line args */
1958     if (n == ac) break;
1959     m = n;
1960 /*    while (*av[m] != '-' && m < ac) m++; */ /* first command */
1961     while (m < ac && *av[m] != '-') m++;  /* first command */
1962     if (m == ac) break;
1963 /* does it take an argument ? and is this argument next ? */
1964 /* check first whether the `-x' is isolated, or arg follows directly */
1965 /* then check whether this is one of those that takes an argument */
1966     if (m+1 < ac &&
1967       *(av[m]+2) == '\0' &&
1968         strchr(takeargs, *(av[m]+1)) != NULL) {
1969       s = av[m];      /*  move command down before non-command */
1970       t = av[m+1];
1971       for (; m > n; m--)  av[m+1] = av[m-1];
1972       av[n] = s;
1973       av[n+1] = t;
1974       n += 2;       /* step over moved args */
1975     }
1976     else {
1977       s = av[m];      /*  move command down before non-command */
1978       for (; m > n; m--)  av[m] = av[m-1];
1979       av[n] = s;
1980       n++;        /* step over moved args */
1981     }
1982   }
1983 }
1984
1985 int test_align (int address, int size, char *name)
1986 {
1987   int n;
1988   if (size > 4) n = address % 4;
1989   else n = address % size;
1990   if (n != 0) {
1991     sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
1992     show_line(log_line, 0);
1993   }
1994   return n;
1995 }
1996
1997 /* activate detailed checking of alignment when trace_flag is set */
1998
1999 void check_fixed_align (int flag)
2000 {
2001   if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2002     show_line("PLEASE RECOMPILE ME!\n", 1);
2003   }
2004 #ifdef CHECKALIGNMENT
2005   if (!flag) return;
2006   test_align ((int) &mem_top, 4, "mem_top");
2007   test_align ((int) &mem_max, 4, "mem_max");
2008   test_align ((int) &mem_min, 4, "mem_min");
2009   test_align ((int) &bad, 4, "bad");
2010   test_align ((int) &trie_size, 4, "trie_size");
2011   test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2012   test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2013   test_align ((int) &name_length, 4, "name_length");
2014   test_align ((int) &first, 4, "first");
2015   test_align ((int) &last, 4, "last");
2016   test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2017   test_align ((int) &pool_ptr, 4, "pool_ptr");
2018   test_align ((int) &str_ptr, 4, "str_ptr");
2019   test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2020   test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2021   test_align ((int) &log_file, 4, "log_file");
2022   test_align ((int) &tally, 4, "tally");
2023   test_align ((int) &term_offset, 4, "term_offset");
2024   test_align ((int) &file_offset, 4, "file_offset");
2025   test_align ((int) &trick_count, 4, "trick_count");
2026   test_align ((int) &first_count, 4, "first_count");
2027   test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2028   test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2029   test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2030   test_align ((int) &use_err_help, 4, "use_err_help");
2031   test_align ((int) &interrupt, 4, "interrupt");
2032   test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2033   test_align ((int) &arith_error, 4, "arith_error");
2034   test_align ((int) &tex_remainder, 4, "tex_remainder");
2035   test_align ((int) &temp_ptr, 4, "temp_ptr");
2036   test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2037   test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2038   test_align ((int) &var_used, 4, "var_used");
2039   test_align ((int) &dyn_used, 4, "dyn_used");
2040   test_align ((int) &avail, 4, "avail");
2041   test_align ((int) &mem_end, 4, "mem_end");
2042   test_align ((int) &mem_start, 4, "mem_start");
2043   test_align ((int) &rover, 4, "rover");
2044   test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2045   test_align ((int) &depth_threshold, 4, "depth_threshold");
2046   test_align ((int) &breadth_max, 4, "breadth_max");
2047   test_align ((int) &nest, sizeof(nest[0]), "nest");
2048
2049 #ifdef ALLOCZEQTB
2050   test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb");  /* not any more ? */
2051 #endif
2052 /*  test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2053   test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2054 /*  test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2055   test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2056
2057   test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2058   test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2059   test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2060   test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2061   test_align ((int) &param_stack, sizeof(param_stack[0]), "param_stack");
2062   test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2063   test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2064   test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2065
2066   test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2067   test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2068   test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2069   test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2070   test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2071   test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2072   test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2073   test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2074   test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2075   test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2076   test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2077   test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2078   test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2079   test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2080   test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2081   test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2082   test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2083   test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2084   test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2085   test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2086   test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2087   test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2088   test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2089   test_align ((int) &param_base, sizeof(param_base[0]), "param_base");
2090
2091 #ifdef ALLOCATEDVIBUF
2092   test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2093 #endif
2094   test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2095   test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2096   test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2097   test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2098   test_align ((int) &background, sizeof(background[0]), "background");
2099   test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2100   test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2101   test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2102   test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2103   test_align ((int) &hc, sizeof(hc[0]), "hc");
2104   test_align ((int) &hu, sizeof(hu[0]), "hu");
2105   test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2106 /*  test_align ((int) &x, sizeof(x[0]), "x"); */
2107
2108   test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2109   test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2110   test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2111   test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2112
2113 /*  test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2114   test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2115   test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2116 /*  test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2117   test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2118
2119   test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2120   test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2121   test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2122   test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2123 #endif
2124 }
2125
2126 void check_alloc_align (int flag) {
2127   if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2128     show_line("PLEASE RECOMPILE ME!\n", 1);
2129 #ifdef CHECKALIGNMENT
2130   if (!flag) return;
2131 #ifndef ALLOCZEQTB
2132   test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb"); 
2133 #endif
2134 #ifndef ALLOCATEDVIBUF
2135   test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf");  /* no op */
2136 #endif
2137   test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2138   test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2139   test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2140   test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2141   test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2142   test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2143   test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2144   test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2145   test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2146 /*  test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2147   test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2148   test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2149   test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2150   test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2151   test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2152 #endif
2153 }
2154
2155 #ifdef HEAPSHOW
2156 void showaddresses (void)
2157 {         /* 96/Jan/20 */
2158   int c;
2159   int d;
2160   sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2161   show_line(log_line, 0);
2162   sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2163   show_line(log_line, 0);
2164   sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n", zdvibuf, xchr, xord, nest);
2165   show_line(log_line, 0);
2166   sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2167        save_stack, input_stack, line_stack, param_stack);
2168   show_line(log_line, 0);
2169   sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2170        font_check, font_size, font_dsize, font_params, font_name);
2171   show_line(log_line, 0);
2172   sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2173       zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2174   show_line(log_line, 0);
2175 }
2176 #endif
2177
2178 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2179
2180 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19  */
2181 /* controlled by USEDVIWINDOINI environment variable            94/June/19 */
2182
2183 bool usedviwindo        = true;               /* use [Environment] section in `dviwindo.ini' */
2184 bool backwardflag       = false;              /* don't cripple all advanced features */
2185 bool shorten_file_name  = false;              /* don't shorten file names to 8+3 for DOS */
2186 char *inifilename       = "dviwindo.ini";     /* name of ini file we look for */
2187 char *dviwindo          = "";                 /* full file name for dviwindo.ini with path */
2188 char *envsection        = "[Environment]";    /* Env var section in `dviwindo.ini' */
2189 char *wndsection        = "[Window]";         /* Window section in `dviwindo.ini' */
2190 char *workdirect        = "WorkingDirectory"; /* key in [Window] section */
2191 bool usesourcedirectory = true;               /* use source file directory as local when WorkingDirectory is set */
2192 bool workingdirectory   = false;              /* if working directory set in ini */
2193 /* set up full file name for dviwindo.ini and check for [Environment] */
2194
2195 bool setupdviwindo (void)
2196 { /* set up full file name for dviwindo.ini */
2197   char dviwindoini[PATH_MAX];
2198   char line[PATH_MAX];
2199   FILE *pinput;
2200   char *windir;
2201   int em = strlen(envsection);
2202   int wm = strlen(wndsection);
2203   int dm = strlen(workdirect);
2204   int wndflag = 0;
2205   int envflag = 0;
2206
2207 /*  Easy to find Windows directory if Windows runs */
2208 /*  Or if user kindly set WINDIR environment variable */
2209 /*  Or if running in Windows NT */  
2210   if ((windir = getenv("windir")) != NULL ||    /* 94/Jan/22 */
2211     (windir = getenv("WINDIR")) != NULL ||
2212     (windir = getenv("winbootdir")) != NULL ||  /* 95/Aug/14 */
2213     (windir = getenv("SystemRoot")) != NULL ||  /* 95/Jun/23 */
2214     (windir = getenv("SYSTEMROOT")) != NULL) {  /* 95/Jun/23 */
2215     strcpy(dviwindoini, windir);
2216     strcat(dviwindoini, "\\");
2217     strcat(dviwindoini, inifilename);
2218 /*    sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2219   }
2220   else {
2221     _searchenv (inifilename, "PATH", dviwindoini);
2222 /*    sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2223   }
2224
2225   wndflag = envflag = 0;
2226 /*  workingdirectory = false; */
2227   if (*dviwindoini != '\0') {
2228     dviwindo = xstrdup(dviwindoini);    /* avoid PATH_MAX string */
2229 /*    check whether dviwindo.ini actually has [Environment] section */
2230     if (share_flag == 0) pinput = fopen(dviwindo, "r");
2231     else pinput = _fsopen(dviwindo, "r", share_flag);
2232     if (pinput != NULL) {
2233       while (fgets (line, sizeof(line), pinput) != NULL) {
2234         if (*line == ';') continue;
2235         if (*line == '\n') continue;
2236         if (*line == '[') {
2237           if (wndflag && envflag) break;  /* escape early */
2238         }
2239         if (_strnicmp(line, wndsection, wm) == 0) {
2240           if (trace_flag) {
2241             sprintf(log_line, "Found %s", line);  /* DEBUGGING */
2242             show_line(log_line, 0);
2243           }
2244           wndflag++;
2245         }
2246         else if (_strnicmp(line, envsection, em) == 0) {
2247           if (trace_flag) {
2248             sprintf(log_line, "Found %s", line);  /* DEBUGGING */
2249             show_line(log_line, 0);
2250           }
2251 /*          fclose(input); */
2252 /*          return true; */
2253           envflag++;
2254         } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2255           if (trace_flag) {
2256             sprintf(log_line, "Found %s", line);  /* DEBUGGING */
2257             show_line(log_line, 0);
2258           }
2259           workingdirectory = true;
2260         }
2261       }
2262       if (envflag) {
2263         (void) fclose(pinput); 
2264         return true;
2265       }
2266       if (trace_flag)
2267         show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2268       (void) fclose(pinput);
2269     }
2270     else if (trace_flag) perrormod(dviwindo);  /* DEBUGGING */
2271     strcpy(dviwindo, ""); /* failed, for one reason or another */
2272   }
2273   return false;
2274 }
2275
2276 /* cache to prevent allocating twice in a row */
2277
2278 char *lastname=NULL, *lastvalue=NULL;
2279
2280 /* get value of env var - try first in dviwindo.ini then DOS env */
2281 /* returns allocated string -- these strings are not freed again */
2282 /* is it safe to do that now ? 98/Jan/31 */
2283 char *grabenv (char *varname)
2284 {
2285   char line[PATH_MAX];
2286   FILE *pinput;
2287   char *s;
2288   int m, n;
2289 /*  int m = strlen(envsection); */
2290 /*  int n = strlen(varname); */
2291
2292   if (varname == NULL) return NULL;   /* sanity check */
2293   if (*varname == '\0') return NULL;    /* sanity check */
2294 /*  speedup to avoid double lookup when called from set_paths in ourpaths.c */
2295 /*  if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2296   if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2297     if (trace_flag) {
2298       sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2299       show_line(log_line, 0);
2300     }
2301 /*    return lastvalue; */        /* save some time here */
2302     return xstrdup(lastvalue);
2303 /*    duplicate so can free safely 98/Jan/31 */
2304   }
2305
2306 /*  hmm, following was not xstrdup(...) */ /* not cached */
2307   if (usedviwindo == 0 || *dviwindo == '\0') {
2308 /*    return getenv(varname); */
2309     s = getenv(varname);
2310     if (s == NULL) return NULL;
2311     else return xstrdup(s);       /* make safe 98/Jan/31 */
2312   }
2313
2314   if (share_flag == 0) pinput = fopen(dviwindo, "r");
2315   else pinput = _fsopen(dviwindo, "r", share_flag);
2316
2317   if (pinput != NULL) {
2318     m = strlen(envsection);
2319 /*    search for [Environment] section */ /* should be case insensitive */
2320     while (fgets (line, sizeof(line), pinput) != NULL) {
2321       if (*line == ';') continue;
2322       if (*line == '\n') continue;
2323       if (_strnicmp(line, envsection, m) == 0) {  /* 98/Jan/31 */
2324 /*        search for varname=... */ /* should be case sensitive ? */
2325         n = strlen(varname);
2326         while (fgets (line, sizeof(line), pinput) != NULL) {
2327           if (*line == ';') continue;
2328           if (*line == '[') break;
2329 /*          if (*line == '\n') break; */  /* ??? */
2330           if (*line <= ' ') continue;   /* 95/June/23 */
2331 /*          if (strncmp(line, varname, n) == 0 && */
2332           if (_strnicmp(line, varname, n) == 0 &&
2333             *(line+n) == '=') { /* found it ? */
2334               (void) fclose (pinput);
2335 /*              flush trailing white space */
2336               s = line + strlen(line) - 1;
2337               while (*s <= ' ' && s > line) *s-- = '\0';
2338               if (trace_flag) { /* DEBUGGING ONLY */
2339                 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2340                 show_line(log_line, 0);
2341               }
2342               s = line+n+1;
2343               if (lastname != NULL) free(lastname);
2344               lastname = xstrdup (varname);
2345               if (lastvalue != NULL) free(lastvalue);
2346               lastvalue = xstrdup(s);
2347               return xstrdup(s);    /* 98/Jan/31 */
2348           }   /* end of matching varname */
2349         }     /* end of while fgets */
2350 /*        break; */ /* ? not found in designated section */    
2351       }       /* end of search for [Environment] section */
2352     }
2353     (void) fclose (pinput);
2354   }           /* end of if fopen */
2355   s = getenv(varname);    /* failed, so try and get from environment */
2356 /*  if (s != NULL) return s;  */
2357   if (s != NULL) {
2358 /*    sdup = xstrdup(s); */   /* just to be safe --- 1995/Jan/31 */
2359     if (lastname != NULL) free(lastname);
2360     lastname = xstrdup (varname);
2361     if (lastvalue != NULL) free(lastvalue);
2362     lastvalue = xstrdup(s);   /* remember in case asked again ... */
2363 /*    return sdup; */
2364     return xstrdup(s);    /* 98/Jan/31 */
2365   }
2366   else return NULL;   /* return NULL if not found anywhere */
2367 }
2368
2369 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2370
2371 void flush_trailing_slash (char *directory)
2372 {
2373   char *s;
2374 /*  flush trailing \ or / in directory, if any 1993/Dec/12 */
2375   if (strcmp(directory, "") != 0) {
2376     s = directory + strlen(directory) - 1;
2377     if (*s == '\\' || *s == '/') *s = '\0';
2378   }
2379 }
2380
2381 void knuthify (void)
2382 {
2383 /*  show_current = false; */ /* show ultimate limits */
2384 /*  reorder_arg_flag = false; */ /* don't reorder command line */
2385 /*  deslash = false; */ /* don't unixify file names */
2386 /*  return_flag = false; */ /* don't allow just ^^M termination */
2387 /*  trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2388   restrict_to_ascii = false; /* don't complain non ASCII */
2389   allow_patterns    = false; /* don't allow pattern redefinition */
2390   show_in_hex       = true;  /* show character code in hex */
2391   show_in_dos       = false; /* redundant with previous */
2392   show_numeric      = false; /* don't show character code decimal */
2393   show_missing      = false; /* don't show missing characters */
2394   civilize_flag     = false; /* don't reorder date fields */
2395   c_style_flag      = false; /* don't add file name to error msg */
2396   show_fmt_flag     = false; /* don't show format file in log */
2397   show_tfm_flag     = false; /* don't show metric file in log */
2398 /* font_max = 255; */ /* revert to TeX 82 limit */
2399 /* if you want this, change in tex.h definition of font_max to `int' */
2400 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2401   tab_step = 0;
2402   show_line_break_stats = false;   /* do not show line break stats */
2403   show_fonts_used = false;
2404   default_rule = 26214;      /* revert to default rule thickness */
2405   pseudo_tilde = false;
2406   pseudo_space = false;
2407   show_texinput_flag = false;
2408   truncate_long_lines = false;
2409   allow_quoted_names = false;
2410   show_cs_names = false;
2411   font_dimen_zero = false;      /* 98/Oct/5 */
2412   ignore_frozen = false;     /* 98/Oct/5 */
2413   suppress_f_ligs = false;      /* 99/Jan/5 */
2414   full_file_name_flag = false;   // 00 Jun 18
2415   save_strings_flag = false;    // 00 Aug 15
2416   knuth_flag = true;       /* so other code can know about this */
2417 } /* end of knuthify */
2418
2419 /* following have already been used up */
2420
2421 /* abcdefghijklmnopqrstuvwxyz */
2422
2423 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2424
2425 /* ........ */
2426
2427 int nohandler = 0;    /* experiment to avoid Ctrl-C interrupt handler */
2428
2429 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2430
2431 /* following made global so analyze_flag can be made separate procedure */
2432
2433 // char *xchrfile=""; /* save space use xstrdup */
2434 char *xchrfile = NULL; /* save space use xstrdup */
2435 // char *replfile="";/* save space use xstrdup */
2436 char *replfile = NULL;/* save space use xstrdup */
2437
2438 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2439
2440 /* analyze command line flag or argument */
2441 /* c is the flag letter itself, while optarg is start of arg if any */
2442
2443 /* when making changes, revise allowedargs */
2444
2445
2446 int analyze_flag (int c, char *optarg)
2447 {
2448   switch (c)  {
2449     case 'v':
2450       want_version = true;
2451       verbose_flag = true;
2452       break;
2453     case 'i':
2454       is_initex = true;
2455       break;
2456     case 'Q':
2457       interaction = batch_mode; /* quiet mode */
2458       break;
2459     case 'R':
2460       interaction = nonstop_mode; /* run mode */
2461       break;
2462     case 'S':
2463       interaction = scroll_mode; /* scroll mode */
2464       break;
2465     case 'T':
2466       interaction = error_stop_mode; /* tex mode */
2467       break;
2468     case 'K':
2469       backwardflag = true; /* 94/Jun/15 */
2470       knuthify();         /* revert to `standard' Knuth TeX */
2471       break;
2472     case 'L':
2473       c_style_flag = true; /* C style error msg 94/Mar/21 */
2474       break;
2475     case 'Z':
2476       show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2477       break;
2478     case 'c':
2479       current_tfm = false; /* not look current dir for TFM */
2480       break;
2481     case 'C':
2482       current_flag = false; /* not look current dir for files */
2483       break;
2484     case 'M':
2485       show_missing = false; /* do not show missing 94/June/10 */
2486       break;
2487     case 'd':
2488       deslash = false; /* flipped 93/Nov/18 */
2489       /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2490       break;
2491     case 'p':
2492       allow_patterns = true; /* 93/Nov/26 */
2493       /* reset_exceptions = true; */ /* 93/Dec/23 */
2494       break;
2495 /*  case 'w':  show_in_hex = false; */ /* 94/Jan/26 */
2496     case 'w':
2497       show_in_hex = true; /* flipped 00/Jun/18 */
2498       break;
2499     case 'j':
2500       show_in_dos = true; /* 96/Jan/26 */
2501       break;
2502     case 'n':
2503       restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2504       break;
2505     case '6':
2506       workingdirectory = true; /* use source dir 98/Sep/29 */
2507       break;
2508     case '7':
2509       usesourcedirectory = false; /* use working dir 98/Sep/29 */
2510       break;
2511     case 'f':
2512       show_fonts_used = false; /* 97/Dec/24 */
2513       break;
2514     case '8':
2515       shorten_file_name = true; /* 95/Feb/20 */
2516       break;
2517     case '9':
2518       show_cs_names = true; /* 98/Mar/31 */
2519       break;
2520     case '4':
2521       ignore_frozen = true; /* 98/Oct/5 */
2522       break;
2523     case '5':
2524       font_dimen_zero = false; /* 98/Oct/5 */
2525       break;
2526     case 'F':
2527       show_texinput_flag = false; /* 98/Jan/28 */
2528       break;
2529 /*  case 'X':  truncate_long_lines = false; */ /* 98/Feb/2 */
2530               /* break; */
2531     case 'W':
2532       usedviwindo = false; /* 94/May/19 */
2533       break;
2534     case 'J':
2535       show_line_break_stats = false; /* 96/Feb/8 */
2536       break;
2537     case 'O':
2538       show_fmt_flag = false; /* 94/Jun/21 */
2539       break;
2540     case 'I':
2541       format_specific = false; /* 95/Jan/7 */
2542       break;
2543     case '3':
2544       encoding_specific = false; /* 98/Oct/5 */
2545       break;
2546     case '2':
2547       suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2548       break;
2549 /* following are pretty obscure */
2550 /*  case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2551 /*            break; */
2552 /*  case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2553 /*            break; */
2554 /*  case 'z': trimeof = false; */ /* 93/Nov/24 */
2555 /*            break; */
2556     case 'z':
2557       full_file_name_flag = false; // 00 Jun 18
2558       break;
2559     case 'X':
2560       save_strings_flag = false; // 00 Aug 15
2561       break;
2562 /* following are unannounced options */ /* some may be recycled ... */
2563     case 't':
2564       trace_flag = true;
2565       break;
2566     case 'q':
2567       quitflag++; /* 93/Dec/16 */
2568       break;
2569 /* The following are really obscure and should not be advertized */
2570     case 's':
2571       show_current = false; /* tex8 93/Dec/14 */
2572       break;
2573     case 'N':
2574       show_numeric = false; /* 93/Dec/21 */
2575       break;
2576     case 'A':
2577       civilize_flag = false; /* 93/Dec/16 */
2578       break; 
2579     case 'B':
2580       open_trace_flag = true; /* openinou 1994/Jan/8 */
2581       break;
2582     case 'Y':
2583       reorder_arg_flag = false; /* local */
2584       break;
2585     case 'b':
2586       test_dir_access = false; /* 94/Feb/10 */
2587       break;
2588     case 'D':
2589       dir_method = false; /* 94/Feb/10 */
2590       break;
2591     case 'G':
2592       file_method = false; /* 94/Feb/13 */
2593       break;
2594 //  case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */ 
2595 /*  case 'X': nohandler++; break; */
2596 /*  case 'f': waitflush = false; break; */
2597 /*  case 'F': floating = true; break; */
2598 /* *********** following command line options take arguments **************  */
2599     case 'm':
2600       if (optarg == 0)
2601         mem_initex = mem_top;
2602       else
2603         mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2604       if (mem_initex == 0)
2605         complainarg(c, optarg);
2606       mem_spec_flag = 1;
2607       break;
2608 #ifdef VARIABLETRIESIZE
2609     case 'h':
2610       if (optarg == 0)
2611         trie_size = default_trie_size;
2612       else
2613         trie_size = atoi(optarg); /* 93 Dec/1 */
2614       if (trie_size == 0)
2615         complainarg(c, optarg);
2616       break;
2617 #endif
2618 #ifdef ALLOCATEHYPHEN
2619     case 'e':
2620       if (optarg == 0)
2621         new_hyphen_prime = hyphen_prime * 2;
2622       else
2623         new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2624       if (new_hyphen_prime == 0)
2625         complainarg(c, optarg);
2626       break;
2627 #endif
2628 #ifdef ALLOCATEDVIBUF
2629     case 'u':
2630       if (optarg == 0)
2631         dvi_buf_size = default_dvi_buf_size;
2632       else
2633         dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2634       if (dvi_buf_size == 0)
2635         complainarg(c, optarg);
2636       break;
2637 #endif
2638     case 'g':
2639       if (optarg == 0)
2640         percent_grow = 62;
2641       else
2642         percent_grow = atoi(optarg); /* 93/Dec/11 */
2643       if (percent_grow == 0)
2644         complainarg(c, optarg);
2645       break;
2646     case 'U':
2647       if (optarg == 0)
2648         pseudo_tilde = 0;
2649       else
2650         pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2651       if (pseudo_tilde > 255)
2652         pseudo_tilde = 255;
2653       else if (pseudo_tilde < 128)
2654         pseudo_tilde = 128;
2655       break;
2656 /*  case 'H':  if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2657  *             if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2658  *             break; */
2659     case 'H':
2660       if (optarg == 0)
2661         tab_step = 8;
2662       else
2663         tab_step = atoi(optarg); /* 94/July/3 */
2664       if (tab_step == 0)
2665         complainarg(c, optarg);
2666       break;
2667     case 'x':
2668       if (optarg == 0)
2669         xchrfile = xstrdup("xchr.map");
2670       else
2671         xchrfile = xstrdup(optarg);
2672       if (xchrfile == NULL || *xchrfile == '\0')
2673         complainarg(c, optarg);
2674       break;
2675     case 'k':
2676       if (optarg == 0)
2677         replfile = xstrdup("repl.key");
2678       else
2679         replfile = xstrdup(optarg);
2680       if (replfile == NULL || *replfile == '\0')
2681         complainarg(c, optarg);
2682       break;
2683 /* more obscure stuff - ppssibly recycle */
2684     case 'P':
2685       if (optarg == 0)
2686         default_rule = 26214; /* 95/Oct/9 */
2687       else
2688         default_rule = atoi(optarg); /* 95/Oct/9 */
2689       if (default_rule == 0)
2690         complainarg(c, optarg);
2691       break;
2692     case 'E':
2693       if (optarg != 0)
2694         putenv(optarg);
2695       else
2696         complainarg(c, optarg);
2697       break;
2698     case 'o':
2699       if (optarg == 0)
2700         dvi_directory = "";
2701       else
2702         dvi_directory = xstrdup(optarg);
2703       if (strcmp(dvi_directory, "") == 0)
2704         complainarg(c, optarg);
2705       break;
2706     case 'l':
2707       if (optarg == 0)
2708         log_directory = "";
2709       else
2710         log_directory = xstrdup(optarg);
2711       if (strcmp(log_directory, "") == 0)
2712         complainarg(c, optarg);
2713       break;
2714     case 'a':
2715       if (optarg == 0)
2716         aux_directory = "";
2717       else
2718         aux_directory = xstrdup(optarg);
2719       if (strcmp(aux_directory, "") == 0)
2720         complainarg(c, optarg);
2721       break;
2722     case '?':
2723     default:
2724       show_use = true;
2725       return -1; // failed to recognize
2726       break;
2727   }
2728   return 0;
2729 }
2730
2731 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2732 //char *yytexcmd="yandytex.cmd";
2733 char *yytexcmd="YANDYTEX.CMD";    /* name of command line file */
2734
2735 /* Try and read default command file - YANDYTEX.CMD */
2736 /* in current directory and then in directory of YANDYTEX */
2737 /* (does not make sense in TeX file directory) */
2738 /* since we don't yet know where that is ! */
2739 /* can't conveniently include this in output file either - not open yet */
2740
2741 /* used both for yytex.cmd and @ indirect command line files */
2742 /* can this be reentered ? */
2743
2744 /* supply extension if none */
2745 void yy_extension (char *fname, char *ext)
2746 {
2747   char *s, *t;
2748   if ((s = strrchr(fname, '.')) == NULL ||
2749     ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2750       strcat(fname, ".");
2751       strcat(fname, ext);
2752   }
2753 }
2754
2755 /* remove file name - keep only path - inserts '\0' to terminate */
2756
2757 void strip_name (char *pathname)
2758 {
2759   char *s;
2760   if ((s = strrchr(pathname, '\\')) != NULL);
2761   else if ((s = strrchr(pathname, '/')) != NULL);
2762   else if ((s = strrchr(pathname, ':')) != NULL) s++;
2763   else s = pathname;
2764   *s = '\0';
2765 }
2766
2767 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2768
2769 char *programpath = ""; /* pathname of program */
2770                     /* redundant with texpath ? */
2771
2772 /* The following does not deslashify arguments ? Do we need to ? */
2773
2774 int read_commands (char *filename)
2775 {
2776   char commandfile[PATH_MAX]; 
2777   FILE *command;
2778   char line[PATH_MAX];
2779   char *linedup;      /* need to copy line to preserve args */
2780   char *s;
2781 /*  char *sn; */
2782   char *optarg;
2783   int c;
2784
2785 /*  Try first in current directory (or use full name as specified) */
2786   strcpy(commandfile, filename);
2787   yy_extension(commandfile, "cmd");
2788   if (share_flag == 0)
2789           command = fopen(commandfile, "r");
2790   else
2791           command = _fsopen(commandfile, "r", share_flag);
2792   if (command == NULL) {
2793 /*    If that fails, try in YANDYTeX program directory */
2794     strcpy(commandfile, programpath);
2795 /*    don't need fancy footwork, since programpath non-empty */
2796     strcat(commandfile, "\\");
2797     strcat(commandfile, filename);
2798     yy_extension(commandfile, "cmd");
2799     if (share_flag == 0)
2800                 command = fopen(commandfile, "r");
2801     else
2802                 command = _fsopen(commandfile, "r", share_flag);
2803     if (command == NULL) {
2804 /*      perrormod(commandfile); */      /* debugging only */
2805 /*      strcpy(commandfile, ""); */   /* indicate failed */
2806       return 0;       /* no command line file YYTEX.CMD */
2807     }
2808   }
2809
2810 /*  allow for multiple lines --- ignore args that don't start with `-' */
2811   while (fgets(line, PATH_MAX, command) != NULL) {
2812 /*    sprintf(log_line, "From %s:\t%s", commandfile, line); */
2813 /*    skip over comment lines and blank lines */
2814     if (*line == '%' || *line == ';' || *line == '\n') continue;
2815     if (strchr(line, '\n') == NULL) strcat(line, "\n");
2816 /*    sfplogline, rintf("From %s:\t%s", commandfile, line); */
2817     linedup = xstrdup (line);         /* 93/Nov/15 */
2818     if (linedup == NULL) {
2819       show_line("ERROR: out of memory\n", 1);    /* read_commands */
2820 //      exit(1);
2821       return -1;    // failure
2822     }
2823     s = strtok(linedup, " \t\n\r");       /* 93/Nov/15 */
2824     while (s != NULL) {
2825       if (*s == '-' || *s == '/') {
2826         c = *(s+1);
2827         optarg = s+2;
2828 /*        if (*optarg = '=') optarg++; */
2829         if (*optarg == '=') optarg++;
2830         if (analyze_flag(c, optarg) < 0) return -1;  // failure ???
2831       }
2832 /*      else break; */              /* ignore non-flag items */
2833       s = strtok(NULL, " \t\n\r");      /* go to next token */
2834     }
2835 /*    If you want to see command lines in file - put -v in the file */
2836 /*    if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2837   }
2838   (void) fclose(command);   /* no longer needed */
2839   return 1;       // success
2840 }
2841
2842 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2843
2844 /* try and read commands on command line */
2845 int read_command_line (int ac, char **av)
2846
2847   int c;
2848   char *optargnew;  /* equal to optarg, unless that starts with `='      */
2849                     /* in which case it is optarg+1 to step over the `=' */
2850                     /* if optarg = 0, then optargnew = 0 also            */
2851
2852 //  show_line("read_command_line\n", 0);
2853   if (ac < 2) return 0;     /* no args to analyze ? 94/Apr/10 */
2854
2855 /*  while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) {              */
2856 /*  NOTE: keep `Y' in there for `do not reorder arguments !                  */
2857 /*  WARNING: if adding flags, change also `allowedargs' and  `takeargs' !!!! */
2858   while ((c = getopt(ac, av, allowedargs)) != EOF) {
2859     if (optarg != 0 && *optarg == '=')
2860       optargnew = optarg+1;
2861     else
2862       optargnew = optarg;
2863     analyze_flag (c, optargnew);
2864   }
2865   if (show_use || quitflag == 3) {
2866 //    showversion (stdout);
2867     stamp_it(log_line);
2868     strcat(log_line, "\n");
2869     show_line(log_line, 0);
2870     stampcopy(log_line);
2871     strcat(log_line, "\n");
2872     show_line(log_line, 0);
2873     if (show_use) show_usage(av[0]);
2874     else if (quitflag == 3) {
2875       strcat(log_line, "\n");
2876       show_line(log_line, 0);
2877     }
2878 //    exit (0);
2879     return -1;        // failure
2880   } 
2881 #ifdef DEBUG
2882   if (floating) testfloating();   /* debugging */
2883 #endif
2884
2885   if (replfile != NULL && *replfile != '\0') {  /* read user defined replacement */
2886     if (read_xchr_file(replfile, 1, av)) {
2887       if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2888       key_replace = true;
2889     }
2890   } 
2891 /*  key_replace used in texmf.c (input_line) */
2892   if (xchrfile != NULL && *xchrfile != '\0') {  /* read user defined xchr[] */
2893     if (read_xchr_file(xchrfile, 0, av)) {
2894       if (trace_flag) show_line("NON ASCII ON\n", 0);
2895       non_ascii = true;
2896     }
2897   } 
2898 /*  non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2899 /*  see also xchr [] & xord [] use in tex3.c and itex.c */
2900   return 0;
2901 }
2902
2903 #ifdef IGNORED
2904 void uppercase (char *s)
2905 {
2906   int c;
2907   while ((c = *s) != '\0') {
2908 /*    if (islower(c)) *s = toupper (*s); */
2909     *s = toupper (*s);
2910     s++;
2911   }
2912 }
2913 #endif
2914
2915 int init_commands (int ac, char **av)
2916 {
2917 /*  NOTE: some defaults changed 1993/Nov/18 */
2918 /*  want_version = show_use = switchflag = return_flag = false;
2919   is_initex = trace_flag = deslash = non_ascii = false; */
2920   is_initex         = false; /* check for dumping format file */
2921   allow_patterns    = false; /* using \pattern after format file loaded */
2922   reset_exceptions  = false;
2923   non_ascii         = false;
2924   key_replace       = false;
2925   want_version      = false;
2926   open_trace_flag   = false;
2927   trace_flag        = false;
2928   verbose_flag      = false;
2929   heap_flag         = false;
2930   restrict_to_ascii = false;
2931   show_in_hex       = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2932   show_in_dos       = false; /* default is not to translate to DOS 850 */ 
2933   return_flag       = true;  // hard wired now
2934   trimeof           = true;  // hard wired now
2935   deslash           = true;
2936   pseudo_tilde      = 254;   /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2937   pseudo_space      = 255;   /* default ' ' replace 97/June/5 nbspace DOS 850 */
2938   default_rule      = 26214; /* default rule variable 95/Oct/9 */
2939   show_current      = true;
2940   civilize_flag     = true;
2941   show_numeric      = true;
2942   show_missing      = true;
2943   current_flag      = true;
2944   current_tfm       = true;  /* search for TFMs in current dir as well */
2945   test_dir_access   = true;  /* test if readable item is perhaps a sub-dir */
2946   dir_method        = true;  /* in dir_p: _findfirst instead of use fopen (nul) */
2947   file_method       = true;  /* use file_p (_findfirst) not readable (access) */
2948 /*  waitflush = true; */  /* flushed 97/Dec/24 */
2949   c_style_flag      = false; /* use c-style error output */
2950   show_fmt_flag     = true;  /* show format file in log */
2951   show_tfm_flag     = false; /* don't show metric file in log */
2952   shorten_file_name     = false; /* don't shorten file names to 8+3 */
2953   show_texinput_flag    = true;  /* show TEXINPUTS and TEXFONTS */
2954   truncate_long_lines   = true; /* truncate long lines */
2955   tab_step              = 0;      /* do not replace tabs with spaces */
2956   format_specific       = true;  /* do format specific TEXINPUTS 95/Jan/7 */
2957   encoding_specific     = true;  /* do encoding specific TEXFONTS 98/Jan/31 */
2958   show_line_break_stats = true;  /* show line break statistics 96/Feb/8 */
2959   show_fonts_used       = true; /* show fonts used in LOG file 97/Dec/24 */
2960   allow_quoted_names    = true;  /* allow quoted names with spaces 98/Mar/15 */
2961   show_cs_names         = false;  /* don't show csnames on start 98/Mar/31 */
2962   knuth_flag            = false;    /* allow extensions to TeX */
2963   cache_file_flag       = true; /* default is to cache full file names 96/Nov/16 */
2964   full_file_name_flag   = true;  /* new default 2000 June 18 */
2965   save_strings_flag     = true; // 2000 Aug 15
2966   errout                = stdout;    /* as opposed to stderr say --- used ??? */
2967   abort_flag            = 0;      // not yet hooked up ???
2968   err_level             = 0;     // not yet hooked up ???
2969   new_hyphen_prime      = 0;
2970 #ifdef VARIABLETRIESIZE
2971 /*  trie_size = default_trie_size; */
2972   trie_size = 0;
2973 #endif
2974   mem_extra_high = 0;
2975   mem_extra_low  = 0;
2976   mem_initex     = 0;
2977 #ifdef ALLOCATEDVIBUF
2978   dvi_buf_size = 0;
2979 #endif
2980 /*  share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2981 /*  share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2982   share_flag = 0; /* revert to fopen for now */
2983
2984 /*  strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2985   programpath = xstrdup(av[0]); /* extract path executable */
2986   strip_name(programpath); /* strip off yandytex.exe */
2987
2988   //format_name = "yandytex";
2989   format_name = "plain"; /* format name if specified on command line */
2990
2991   encoding_name = "";
2992
2993   if (read_commands(yytexcmd) < 0)   /* read yandytex.cmd 1994/July/12 */
2994     return -1;            // in case of error
2995
2996   if (read_command_line(ac, av) < 0)  /* move out to subr 94/Apr/10 */
2997     return -1;            // in case of error
2998
2999   if (optind == 0) optind = ac;   /* no arg case paranoia 94/Apr/10 */
3000
3001 /*  Print version *after* banner ? */ /* does this get in log file ? */
3002   if (want_version) {
3003 //  showversion (stdout);
3004 //  showversion (log_line);
3005     stamp_it(log_line);
3006     strcat(log_line, "\n");
3007     show_line(log_line, 0);
3008     stampcopy(log_line);
3009     strcat(log_line, "\n");
3010     show_line(log_line, 0);
3011   }
3012 /*  if (show_use) show_usage(av[0]);   */  /* show usage and quit */
3013
3014 /*  if we aren't including current directory in any directory lists */
3015 /*  then makes no sense to avoid them separately for TFM files ... */
3016 /*  (that is, the ./ is already omitted from the dir list in that case */
3017   if (!current_flag && !current_tfm)
3018     current_tfm = true; /* 94/Jan/24 */
3019   return 0;               // success
3020 }
3021
3022 /* E sets environment variable ? */
3023
3024 void initial_memory (void)
3025 {
3026   /* set initial memory allocations */
3027   if (mem_extra_high < 0) mem_extra_high = 0;
3028   if (mem_extra_low < 0) mem_extra_low = 0;
3029   if (mem_initex < 0) mem_initex = 0;
3030   if (is_initex) {
3031  #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
3032     if (mem_extra_high != 0 || mem_extra_low != 0) {
3033       show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
3034       mem_extra_high = 0;   mem_extra_low = 0;
3035     }
3036 #endif
3037   } else {
3038     if (mem_initex != 0) {
3039       show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3040       mem_initex = 0;
3041     }
3042     if (trie_size != 0) {
3043       show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3044 /* trie_size = 0; */
3045     }
3046   }
3047   if (mem_initex == 0) mem_initex = default_mem_top;
3048   if (trie_size == 0) trie_size = default_trie_size;
3049 /* Just in case user mistakenly specified words instead of kilo words */
3050   if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3051   if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3052   if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3053 #ifdef ALLOCATEHIGH         /* not used anymore */
3054   if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3055     show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3056     mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3057   }
3058 #endif
3059 #ifdef ALLOCATELOW          /* not used anymore */
3060   if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3061     show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3062     mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3063   }
3064 #endif
3065   if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3066     show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3067 /* mem_initex = 2048 * 1024; */
3068   }
3069  #ifdef ALLOCATEDVIBUF
3070   if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3071 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3072   if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3073   if (dvi_buf_size % 8 != 0)        /* check multiple of eight */
3074     dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3075  #endif
3076   if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3077   if (new_hyphen_prime > 0) {
3078     if (! is_initex)
3079       show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3080     else {
3081       if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3082       while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3083       if (trace_flag) {
3084         sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3085         show_line(log_line, 0);
3086       }
3087     }
3088   }
3089   if (percent_grow > 100) percent_grow = percent_grow - 100;
3090   if (percent_grow > 100) percent_grow = 100;   /* upper limit - double */
3091   if (percent_grow < 10) percent_grow = 10;   /* lower limit - 10% */
3092 }
3093
3094 /**********************************************************************/
3095
3096 void perrormod (char *s)
3097 {
3098   sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3099   show_line(log_line, 1);
3100 }
3101
3102 void pause (void)
3103 {
3104 #ifndef _WINDOWS
3105   fflush(stdout);     /* ??? */
3106   fflush(stderr);     /* ??? */
3107   (void) _getch();    /* ??? */
3108 #endif
3109 }
3110
3111 void checkpause (int flag)
3112 {            /* 95/Oct/28 */
3113   char *s;
3114   int debug_pause = 0;
3115 /*  don't stop if in Q (quiet) or R (run) mode */
3116 /*  stop only in S (scroll) and T (TeX) mode */
3117   if (interaction >= 0 && interaction < 2) flag = 0;    /* 98/Jun/30 */
3118   s = grabenv("DEBUGPAUSE");
3119   if (s != NULL) sscanf(s, "%d", &debug_pause);
3120   if (flag < 0) return;
3121   if (debug_pause) {
3122     if (debug_pause || flag > 0) {
3123       show_line("\n", 0);
3124 #ifndef _WINDOWS
3125       show_line("Press any key to continue . . .\n", 0);
3126       pause();
3127 #endif
3128     }
3129   }
3130 }
3131
3132 void check_enter (int argc, char *argv[])
3133 {/* 95/Oct/28 */
3134   int m;
3135   char current[FILENAME_MAX];
3136   if (grabenv("DEBUGPAUSE") != NULL) {
3137     (void) _getcwd(current, sizeof(current));
3138     sprintf(log_line, "Current directory: `%s'\n", current);
3139     show_line(log_line, 0);
3140     for (m = 0; m < argc; m++) {
3141       sprintf(log_line, "%2d: `%s'\n", m, argv[m]); 
3142       show_line(log_line, 0);
3143     }
3144     checkpause(-1);
3145   }
3146 }
3147
3148 #ifdef IGNORED
3149 void checkexit (int n) {              /* 95/Oct/28 */
3150   checkpause(1);
3151   exit(n);
3152 }
3153 #endif
3154
3155 /*************************************************************************/
3156
3157 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3158 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3159 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3160 /* this is then undone in tex3.c both for fopen input and output */
3161 /* not ideal, since pseudo name appears in log and in error messages ... */
3162
3163 void hidetwiddle (char *name)
3164 {
3165   char *s=name;
3166 #ifdef DEBUGTWIDDLE
3167   if (trace_flag) {
3168     sprintf(log_line, "Hidetwiddle %s", name);
3169     show_line(log_line, 0);
3170   }
3171 #endif
3172 /*  while (*s != '\0' && *s != ' ') { */
3173   while (*s != '\0')  {
3174     if (*s == '~' && pseudo_tilde != 0)
3175       *s = (char) pseudo_tilde;  /* typically 254 */
3176     else if (*s == ' ' && pseudo_space != 0)
3177       *s = (char) pseudo_space;  /* typically 255 */
3178     s++;
3179   }
3180 #ifdef DEBUGTWIDDLE
3181   if (trace_flag) {
3182     sprintf(log_line, "=> %s\n", name);
3183     show_line(log_line, 0);
3184   }
3185 #endif
3186 }
3187
3188 void deslash_all (int ac, char **av)
3189 {
3190   char buffer[PATH_MAX];  
3191   char *s;
3192
3193   if ((s = getenv("USEDVIWINDOINI")) != NULL) 
3194     sscanf(s, "%d", &usedviwindo);      /* 94/June/14 */
3195
3196   if (usedviwindo) setupdviwindo();   // moved to yandytex ?
3197
3198   check_enter(ac, av);           /* 95/Oct/28 */
3199
3200 /* environment variables for output directories (as in PC TeX) */
3201
3202   if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3203   if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3204   if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3205
3206   strcpy(buffer, av[0]);            /* get path to executable */
3207   if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3208   else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3209   else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3210   s = buffer + strlen(buffer) - 1;
3211   if (*s == '\\' || *s == '/') *s = '\0';   /* flush trailing PATH_SEP */
3212   texpath = xstrdup(buffer);
3213
3214 /*  Hmm, we may be operating on DOS environment variables here !!! */
3215
3216   if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3217   if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3218   if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3219
3220   if (deslash) {
3221       unixify (texpath);          /* 94/Jan/25 */
3222 /* if output directories given, deslashify them also 1993/Dec/12 */
3223       if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3224       if (strcmp(log_directory, "") != 0) unixify(log_directory);
3225       if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3226   }
3227
3228 /*  deslash TeX source file (and format, if format specified) */
3229 /*  and check args to see whether format was specified */
3230   format_spec = 0;
3231 /*  NOTE: assuming that command line arguments are in writable memory ! */
3232 /*  if (trace_flag || debug_flag)
3233     sprintf(log_line, "optind %d ac %d\n", optind, ac); */   /* debugging */ 
3234 /*  if (optind < ac) { */           /* bkph */
3235   if (optind < ac && optind > 0) {      /* paranoia 94/Apr/10 */
3236     if (deslash) {
3237       if (trace_flag || debug_flag) {
3238         sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3239           optind, av[optind], ac);
3240         show_line(log_line, 0);
3241       }
3242       unixify(av[optind]);
3243     }
3244     if (pseudo_tilde != 0 || pseudo_space != 0)
3245       hidetwiddle (av[optind]);     /* 95/Sep/25 */
3246 /* For Windows NT, lets allow + instead of & for format specification */
3247     if (*av[optind] == '&' || *av[optind] == '+') {
3248       format_spec = 1; /* format file specified */
3249       format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3250 /*      uppercase (format_name); */    /* why ? 98/Jan/31 */
3251       if (optind + 1 < ac) {
3252         if (deslash) {
3253           if (trace_flag || debug_flag) {
3254             sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3255               optind+1, av[optind+1], ac);
3256             show_line(log_line, 0);
3257           }
3258           unixify(av[optind+1]);
3259         }
3260         if (pseudo_tilde != 0 || pseudo_space != 0)
3261           hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3262       }
3263     }         
3264   }
3265 }
3266
3267 /* The above seems to assume that arguments that don't start with '-' */
3268 /* are file names or format names - what if type in control sequences? */
3269
3270 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3271
3272 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3273 /* interaction == 1 => nonstop mode (omit all stops)                        */
3274 /* interaction == 2 => scroll mode (omit error stops)                       */
3275 /* interaction == 3 => error_stop mode (stops at every opportunity)         */
3276
3277 /* main entry point follows */
3278
3279 /* this gets called pretty much right away in `main' in texmf.c */
3280
3281 /* note: those optarg == 0 test don't really work ... */
3282 /* note: optarg starts at = in case of x=... */
3283
3284 int init (int ac, char **av)
3285 {
3286   char initbuffer[PATH_MAX];
3287   int k;
3288   
3289   debugfile = getenv("TEXDEBUG");     /* 94/March/28 */
3290   if (debugfile)
3291     debug_flag = 1;
3292   else
3293     debug_flag = 0;
3294
3295   if (debug_flag) {
3296     show_line("TEXDEBUG\n", 0);
3297     trace_flag = 1;            /* 94/April/14 */
3298   }
3299
3300   if (sizeof(memory_word) != 8) {  /* compile time test */
3301     sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3302     show_line(log_line, 1);
3303   }
3304
3305   start_time = clock();    /* get time */
3306   main_time = start_time;   /* fill in, in case file never opened */
3307
3308   initbuffer[0] = '\0';         /* paranoia 94/Apr/10 */
3309
3310 /*  reset all allocatable memory pointers to NULL - in case we drop out */
3311   mainmemory = NULL;
3312   font_info = NULL;
3313   str_pool = NULL;
3314   str_start = NULL;
3315 #ifdef ALLOCATEZEQTB
3316   zeqtb = NULL;
3317 #endif
3318 #ifdef ALLOCATEHASH
3319   zzzae = NULL;
3320 #endif
3321 #ifdef ALLOCATESAVESTACK
3322   save_stack = NULL; 
3323 #endif
3324 #ifdef ALLOCATEDVIBUF
3325   zdvibuf = NULL; 
3326 #endif
3327 #ifdef ALLOCATEBUFFER
3328   buffer = NULL;        /* new 1999/Jan/7 need to do early */
3329   current_buf_size = 0;
3330   buffer = realloc_buffer (initial_buf_size);
3331 /*  sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3332 #endif
3333   hyph_list = NULL; hyph_word = NULL;
3334   trie_taken = NULL; trie_hash = NULL;
3335   trie_r = NULL;
3336   trie_c = NULL;
3337   trie_o = NULL;
3338   trie_l = NULL;
3339   trie_trc = NULL;
3340   trie_tro = NULL;
3341   trie_trl = NULL;
3342
3343   log_opened = false;       /* so can tell whether opened */
3344   interaction = -1;       /* default state => 3 */
3345   missing_characters = 0;      /* none yet! */
3346   workingdirectory = false;   /* set from dviwindo.ini & command line */
3347   font_dimen_zero = true;     /* \fontdimen0 for checksum 98/Oct/5 */
3348   ignore_frozen = false;     /* default is not to ignore 98/Oct/5 */
3349   suppress_f_ligs = false;      /* default is not to ignore f-ligs */
3350 /*  if (*av[1] == '-Y') reorder_arg_flag = false; */  /* 94/April/14 */
3351   if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3352
3353   if (reorder_arg_flag) reorderargs(ac, av);  
3354
3355   if (init_commands(ac, av))
3356     return -1;          // failure
3357
3358   check_fixed_align(trace_flag);       /* sanity check 1994/Jan/8 */
3359
3360   format_file   = NULL;       /* to be set in openinou.c 94/Jun/21 */
3361   string_file   = NULL;       /* to be set in openinou.c 96/Jan/15 */
3362   source_direct = NULL;       /* to be set in openinou.c 98/Sep/29 */
3363   dvi_file_name = NULL;       /* to be set in openinou.c 00/Jun/18 */
3364   log_file_name = NULL;       /* to be set in openinou.c 00/Jun/18 */
3365
3366   first_pass_count  = 0;
3367   second_pass_count = 0;
3368   final_pass_count  = 0;
3369   paragraph_failed  = 0;
3370   singleline        = 0;
3371   overfull_hbox     = 0;
3372   underfull_hbox    = 0;
3373   overfull_vbox     = 0;
3374   underfull_vbox    = 0;
3375
3376   closed_already=0;        // so can only do once
3377
3378   if (trace_flag) show_line("Entering init (local)\n", 0);
3379
3380 /*   Print version *after* banner ? */ /* does this get in log file ? */
3381
3382   probe_memory();             /* show top address */
3383   ini_max_address = max_address;       /* initial max address */
3384   if (trace_flag) show_maximums(stdout);
3385 #ifdef HEAPWALK
3386   if (heap_flag) (void) heap_dump(stdout, 1);
3387 #endif
3388
3389   initial_memory();
3390
3391   deslash_all(ac, av);    /* deslash and note if format specified */
3392
3393 /*  sprintf(log_line, "%s\n", initbuffer); */    /* debugging, remove later */
3394
3395   no_interrupts = 0;
3396
3397   if (format_spec && mem_spec_flag) {
3398     show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3399   }
3400
3401    if (allocate_memory() != 0)   /* NOW, try and ALLOCATE MEMORY if needed */
3402      return -1;         // if failed to allocate
3403
3404 /*   following is more or less useless since most all things not yet alloc */
3405    check_alloc_align(trace_flag);    /* sanity check 1994/Jan/8 */
3406 #ifdef HEAPSHOW
3407    if (trace_flag) showaddresses();  /* debugging only 1996/Jan/20 */
3408 #endif
3409
3410 #ifdef HEAPWALK
3411 /*   if (heap_flag) heap_dump(stdout, 1); */  /* redundant ? */
3412 #endif
3413
3414     if (trace_flag) show_line("Leaving init (local)\n", 0);
3415     return 0;         // success
3416 }
3417
3418 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK  CLOCKS_PER_SEC */
3419
3420 /* void show_inter_val (clock_t start, clock_t end) { */
3421 void show_inter_val (clock_t interval)
3422 {
3423 /*  clock_t interval; */
3424 /*  int seconds, tenths; */
3425 /*  int seconds, tenths, hundredth;  */
3426   int seconds, tenths, hundredth, thousands;
3427 /*  interval = end - start; */
3428 /*  sanity check whether positive ? */
3429   if (interval >= CLK_TCK * 10) {
3430     tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK; 
3431     seconds = tenths / 10; 
3432     tenths = tenths % 10;
3433     sprintf(log_line, "%d.%d", seconds, tenths);
3434     show_line(log_line, 0);
3435   }
3436   else if (interval >= CLK_TCK) {       /* 94/Feb/25 */
3437     hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK; 
3438     seconds = hundredth / 100;
3439     hundredth = hundredth % 100;
3440     sprintf(log_line, "%d.%02d", seconds, hundredth);
3441     show_line(log_line, 0);
3442   }
3443   else if (interval > 0) {          /* 94/Oct/4 */
3444     thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;  
3445     seconds = thousands / 1000;
3446     thousands = thousands % 1000;
3447     sprintf(log_line, "%d.%03d", seconds, thousands);
3448     show_line(log_line, 0);
3449   }
3450   else show_line("0", 0);          /* 95/Mar/1 */
3451 }
3452
3453 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3454 /* shows various times, warning about missing chars */
3455
3456 int endit (int flag)
3457 {
3458 /*  int msec; */
3459   finish_time = clock();
3460   if (missing_characters != 0) flag = 1;
3461   if (missing_characters) {
3462     sprintf(log_line,
3463                 "! There %s %d missing character%s --- see log file\n",
3464                 (missing_characters == 1) ? "was" : "were",  missing_characters,
3465                 (missing_characters == 1) ? "" : "s");
3466     show_line(log_line, 0);
3467   }
3468   if (free_memory() != 0) flag++;
3469 /*  dumpaccess(); */
3470 /*  show per page time also ? */
3471   if (verbose_flag) {
3472 /*    sprintf(log_line, "start %ld main %ld finish %ld\n",
3473       start_time, main_time, finish_time); */
3474     show_line("Total ", 0);
3475 /*    show_inter_val(start_time, finish_time); */
3476     show_inter_val(finish_time - start_time);
3477     show_line(" sec (", 0);
3478 /*    show_inter_val(start_time, main_time); */
3479     show_inter_val(main_time - start_time);
3480     show_line(" format load + ", 0);
3481 /*    show_inter_val(main_time, finish_time); */
3482     show_inter_val(finish_time - main_time);
3483     show_line(" processing) ", 0);
3484     if (total_pages > 0) {
3485 /*      msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3486 /*      sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3487 /*      sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3488       show_inter_val ((finish_time - main_time) / total_pages);
3489       show_line(" sec per page", 0);
3490     }
3491     show_line("\n", 0);
3492   }
3493
3494   checkpause(flag);
3495 //  checkpause(1);
3496   return flag;
3497 }
3498
3499 /********************************************************************************/
3500
3501 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3502
3503 int textcolumn;
3504
3505 #define MAXCOLUMN 78
3506
3507 void print_cs_name (FILE *output, int h)
3508 {
3509   int c, textof, n;
3510   char *s;
3511   
3512   textof = hash[h].v.RH;
3513   if (textof == 0) return;  /* ignore if text() == 0 */
3514   n = length(textof);
3515   if (textcolumn != 0) {
3516     sprintf(log_line, ", ");
3517     if (output != NULL) fprintf(output, log_line);
3518     else show_line(log_line, 0);
3519     textcolumn += 2;
3520   }
3521   if (textcolumn + n + 2 >= MAXCOLUMN) {
3522     sprintf(log_line, "\n");
3523     if (output == stderr) show_line(log_line, 1);
3524     else if (output == stdout) show_line(log_line, 0);
3525     else fputs(log_line, output);
3526     textcolumn=0;
3527   }
3528   s = log_line;
3529   for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3530     *s++ = str_pool[c];
3531   }
3532   if (output == stderr) show_line(log_line, 1);
3533   else if (output == stdout) show_line(log_line, 0);
3534   else fprintf(output, log_line);
3535   textcolumn += n;
3536 }
3537
3538 int compare_strn (int, int, int, int); /* in tex9.c */
3539
3540 /* compare two csnames in qsort */
3541
3542 int compare_cs (const void *cp1, const void *cp2)
3543 {
3544   int c1, c2, l1, l2, k1, k2, textof1, textof2;
3545   c1 = *(int *)cp1;
3546   c2 = *(int *)cp2;
3547   textof1 = hash[c1].v.RH;
3548   textof2 = hash[c2].v.RH;
3549   l1 = length(textof1); 
3550   l2 = length(textof2); 
3551   k1 = str_start[textof1]; 
3552   k2 = str_start[textof2]; 
3553 /*  showstring (k1, l1); */
3554 /*  showstring (k2, l2); */
3555   return compare_strn (k1, l1, k2, l2);
3556 }
3557
3558 char *csused=NULL;
3559
3560 /* Allocate table of indeces to allow sorting on csname */
3561 /* Allocate flags to remember which ones already listed at start */
3562
3563 void print_cs_names (FILE *output, int pass)
3564 {
3565   int h, k, ccount, repeatflag;
3566   int *cnumtable;
3567   int nfcs = hash_base + hash_size + hash_extra;  /* frozen_control_sequence */
3568
3569   if (pass == 0 && csused == NULL) {
3570     csused = (char *) malloc (nfcs);
3571     if (csused == NULL) return; 
3572 #ifdef USEMEMSET
3573     memset(csused, 0, nfcs); 
3574 #else
3575     for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3576 #endif
3577   }
3578
3579   ccount=0;
3580   for (h = hash_base + 1; h < nfcs; h++) {
3581     if (pass == 1 && csused[h]) continue;
3582     if (hash[h].v.RH != 0) {
3583       if (pass == 0) csused[h] = 1;
3584       ccount++;
3585     }
3586   }
3587
3588   sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3589       ccount, (pass == 1) ? "new" : "");
3590   if (output == stderr) show_line(log_line, 1); 
3591   else if (output == stdout) show_line(log_line, 0);  
3592   else fprintf(output, log_line);
3593
3594   if (ccount > 0) { /* don't bother to get into trouble */
3595     textcolumn=0;
3596     cnumtable = (int *) malloc (ccount * sizeof(int));
3597     if (cnumtable == NULL) return;
3598
3599     ccount=0;
3600 /*    for (h = 515; h < (hash_size + 780); h++) { */
3601     for (h = hash_base+1; h < nfcs; h++) {
3602       if (pass == 1 && csused[ h]) continue; 
3603       if (hash[h].v.RH != 0) cnumtable[ccount++] = h;
3604     }
3605
3606     qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3607
3608     repeatflag = 0;
3609     for (k = 0; k < ccount; k++) {
3610       h = cnumtable[ k];
3611       if (pass == 1 && csused[ h]) continue; 
3612       print_cs_name(output, h);
3613     }
3614     sprintf(log_line, "\n");
3615     if (output == stderr) show_line(log_line, 1);
3616     else if (output == stdout) show_line(log_line, 0);
3617     else fprintf(output, log_line);
3618     free((void *)cnumtable);
3619   }
3620
3621   if (pass == 1 && csused != NULL) {
3622     free(csused);
3623     csused = NULL;
3624   }
3625 }
3626
3627 /***************** font info listing moved from TEX9.C ******************/
3628
3629 void showstring (int k, int l)
3630 {
3631   char *s=log_line;
3632   while (l-- > 0) *s++ = str_pool[k++];
3633   *s++ = ' ';
3634   *s = '\0';
3635   show_line(log_line, 0);
3636 }
3637
3638 /* compare two strings in str_pool (not null terminated) */
3639 /* k1 and k2 are positions in string pool */
3640 /* l1 and l2 are lengths of strings */
3641
3642 int compare_strn (int k1, int l1, int k2, int l2)
3643 {
3644   int c1, c2;
3645 /*  while (l1-- > 0 && l2-- > 0) { */
3646   while (l1 > 0 && l2 > 0) {
3647     c1 = str_pool[k1];
3648     c2 = str_pool[k2];
3649 /*    sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3650     if (c1 > c2) return 1;
3651     else if (c2 > c1) return -1;
3652     l1--; l2--;
3653     k1++; k2++;
3654   }
3655   if (l1 > 0) return 1;   /* first string longer */
3656   else if (l2 > 0) return -1; /* second string longer */
3657   return 0;         /* strings match */
3658 }
3659
3660 /* compare two font names and their at sizes in qsort */
3661
3662 int compare_fnt (const void *fp1, const void *fp2)
3663 {
3664   int f1, f2, l1, l2, k1, k2, s;
3665   f1 = *(short *)fp1;
3666   f2 = *(short *)fp2;
3667   l1 = length(font_name[f1]);
3668   l2 = length(font_name[f2]);
3669   k1 = str_start[font_name[f1]]; 
3670   k2 = str_start[font_name[f2]]; 
3671 /*  showstring (k1, l1); */
3672 /*  showstring (k2, l2); */
3673   s = compare_strn (k1, l1, k2, l2);
3674 /*  sprintf(log_line, "%d\n", s); */
3675   if (s != 0) return s;
3676   if (font_size[f1]> font_size[f2]) return 1;
3677   else if (font_size[f1]< font_size[f2]) return -1;
3678   return 0;         /* should not ever get here */
3679 }
3680
3681 /* compare two font names */
3682
3683 int compare_fnt_name (int f1, int f2)
3684 {
3685   int l1, l2, k1, k2, s;
3686   l1 = length(font_name[f1]);
3687   l2 = length(font_name[f2]); 
3688   k1 = str_start[font_name[f1]]; 
3689   k2 = str_start[font_name[f2]]; 
3690 /*  showstring (k1, l1); */
3691 /*  showstring (k2, l2); */
3692   s = compare_strn (k1, l1, k2, l2);
3693 /*  sprintf(log_line, "%d\n", s); */
3694   return s;
3695 }
3696
3697 /* decode checksum information */
3698
3699 unsigned long checkdefault = 0x59265920;  /* default signature */
3700
3701 int decode_fourty (unsigned long checksum, char *codingvector)
3702 {
3703   int c;
3704   int k;
3705 /*  char codingvector[6+1]; */
3706
3707 /*  if (checksum == checkdefault) { */
3708   if (checksum == 0) {
3709 /*    strcpy(codingvector, "unknown"); */
3710     strcpy(codingvector, "unknwn");
3711     return 1;
3712   }
3713   else if ((checksum >> 8) == (checkdefault >> 8)) {  /* last byte random */
3714 /*    strcpy (codingvector,  "native"); */  /* if not specified ... */
3715     strcpy (codingvector,  "fixed ");   /* if not specified ... */
3716     return 1;               /* no info available */
3717   }
3718   else {
3719     for (k = 0; k < 6; k++) {
3720       c = (int) (checksum % 40);
3721       checksum = checksum / 40;
3722       if (c <= 'z' - 'a')c = c + 'a';
3723       else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3724       else if (c == 36) c = '-';
3725       else if (c == 37) c = '&';
3726       else if (c == 38) c = '_';
3727       else c = '.';       /* unknown */
3728       codingvector[5-k] = (char) c;
3729     }
3730     codingvector[6] = '\0';
3731   }
3732 /*  sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3733   return 0;         /* encoding info returned in codingvector */
3734 }
3735
3736 double sclpnt (long x)
3737 {
3738   double pt;
3739   pt = (double) x / 65536.0;
3740   pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3741   return (pt);
3742 }
3743
3744 // Shows list of fonts in log file
3745
3746 void dvi_font_show(internal_font_number f, int suppressname)
3747 {
3748   int a, l, k, n, for_end;
3749   unsigned long checksum;
3750   char checksumvector[8];
3751   char buffer[32];
3752
3753 /*  fprintf (log_file, "DAMN! %d ", suppressname); */
3754 /*  fprintf (log_file, "%d ", suppressname); */
3755 /*  suppressname = 0; */
3756   putc(' ', log_file);
3757   if (suppressname == 0) {
3758     a = length(font_area[f]); 
3759     l = length(font_name[f]); 
3760     k = str_start[font_area[f]];
3761     for_end = str_start[font_area[f]+ 1]- 1;
3762     if (k <= for_end) do {
3763       putc(str_pool[k], log_file);
3764     } while(k++ < for_end, stdout); 
3765     k = str_start[font_name[f]];
3766     for_end = str_start[font_name[f]+ 1]- 1;
3767     if (k <= for_end) do {
3768       putc(str_pool[k], log_file);
3769     } while(k++ < for_end);
3770   }
3771   else a = l = 0;
3772   for (k = a+l; k < 16; k++) putc(' ', log_file);
3773   sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3774   fputs(buffer, log_file);
3775 //  fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3776   if (suppressname == 0) {
3777     n = strlen(buffer);
3778 //    n = strlen(log_file);
3779     for (k = n; k < 16; k++) putc(' ', log_file);
3780     checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3781           font_check[f].b2) << 8 | font_check[f].b3;
3782     decode_fourty(checksum, checksumvector);
3783     fprintf(log_file, "encoding: %s..", checksumvector);
3784   }
3785   putc('\n', log_file);
3786 }
3787
3788 /* Allocate table of indeces to allow sorting on font name */
3789
3790 void show_font_info (void)
3791 {
3792   int k, m, fcount, repeatflag;
3793   short *fnumtable;
3794
3795   fcount=0;
3796   for (k = 1; k <= font_ptr; k++)
3797     if (font_used[k])fcount++;
3798
3799   if (fcount == 0) return;  /* don't bother to get into trouble */
3800
3801   fnumtable = (short *) malloc (fcount * sizeof(short));
3802
3803 /*  if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3804
3805   fprintf(log_file, "\nUsed %d font%s:\n",
3806       fcount, (fcount == 1) ? "" : "s");
3807
3808   fcount=0;
3809   for (k = 1; k <= font_ptr; k++) 
3810     if (font_used[k])fnumtable[fcount++] = (short) k;
3811
3812   qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3813
3814   repeatflag = 0;
3815   for (m = 0; m < fcount; m++) {
3816     if (m > 0) {
3817       if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3818         repeatflag = 1;
3819       else repeatflag = 0;
3820     }
3821     dvi_font_show(fnumtable[ m], repeatflag);
3822   }
3823
3824   free((void *)fnumtable);
3825 }
3826
3827 ////////////////////////////////////////////////////////////////////////////
3828
3829 // Here follows the new stuff for the DLL version
3830
3831 #ifdef _WINDOWS
3832
3833 int showlineinx=0;
3834
3835 #define SHOWLINEBUFLEN 256
3836
3837 char showlinebuf[SHOWLINEBUFLEN];
3838
3839 // char log_line[MAXLINE];
3840
3841 #define WHITESPACE " \t\n\r"
3842
3843 HINSTANCE hInstanceDLL=NULL;    /* remember for this DLL */
3844
3845 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3846
3847 #define GET_WM_COMMAND_CMD(wParam, lParam)  (HIWORD(wParam))
3848 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3849 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3850
3851 HWND hConsoleWnd=NULL;    /* Console Text Window Handle passed from DVIWindo */
3852
3853 void ClearShowBuffer (void)
3854 {
3855   showlinebuf[showlineinx++] = '\0';    // clear out accumulated stuff
3856   if (hConsoleWnd != NULL)
3857     SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3858   showlineinx = 0;
3859 }
3860
3861 // communicate with DVIWindo (for yandytex.dll)
3862
3863 void show_line (char *line, int errflag) {     /* 99/June/11 */
3864   int ret;
3865
3866   if (IsWindow(hConsoleWnd) == 0) {   // in case the other end died
3867     sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3868     ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3869     hConsoleWnd = NULL;
3870 //    abort_flag++;            // kill job in this case ???
3871     return;
3872   }
3873
3874   if (showlineinx > 0) ClearShowBuffer();
3875
3876   if (hConsoleWnd != NULL)
3877     SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3878
3879   if (errflag) {
3880     err_level++;
3881     ret =  MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3882     if (ret == IDCANCEL) {
3883 //      abort_flag++;
3884       uexit(1);   // dangerous reentry possibility ?
3885     }
3886   }
3887 }
3888
3889 //  Provide means for buffering up individual characters
3890
3891 void show_char (int chr) {
3892   if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3893   showlinebuf[showlineinx++] = (char) chr;
3894   if (chr == '\n') ClearShowBuffer();
3895 }
3896
3897 void winshow(char *line) {
3898   (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3899 }
3900
3901 void winerror (char *line) {
3902   int ret;
3903   ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3904   if (ret == IDCANCEL) abort_flag++;
3905 }
3906
3907 // argument info constructed from command line 
3908
3909 int xargc;
3910
3911 char **xargv=NULL;
3912
3913 // need to be careful here because of quoted args with spaces in them
3914 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3915
3916 int makecommandargs (char *line)
3917 {
3918   int xargc;
3919 //  char *s, *t;
3920   unsigned char *s, *t;       // fix 2000 June 18
3921
3922   if (line == NULL) return -1;    /* sanity check */
3923
3924 //  winerror(line);           // debugging only
3925
3926 //  s = strtok(line, WHITESPACE);
3927 //  while (s != NULL) {         /* count arguments */
3928 //    xargc++;
3929 //    s = strtok(NULL, WHITESPACE);
3930 //  }
3931
3932   xargc = 0;
3933   s = line;
3934   while (*s != '\0') {
3935     while (*s <= 32 && *s > 0) s++;
3936     if (*s == '\0') break;
3937     t = s;
3938     while (*t > 32 && *t != '\"') t++;
3939     if (*t == '\"') {
3940       t++;
3941       while (*t > 0 && *t != '\"') t++;
3942       if (*t == '\0') break;
3943       t++;
3944     }
3945 //    xargv[xargc] = s;
3946     xargc++;
3947     if (*t == '\0') break;
3948 //    *t = '\0';
3949     s = t+1;
3950   }
3951
3952   if (xargc == 0) return -1;      /* nothing to do */
3953
3954   xargv = (char **) malloc(xargc * sizeof(char *));
3955   if (xargv == NULL) {
3956     sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3957     winerror(log_line);
3958     return -1;
3959   }
3960
3961   xargc = 0;
3962   s = line;
3963   while (*s != '\0') {
3964     while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3965     if (*s == '\0') break;
3966     t = s;
3967     while (*t > ' ' && *t != '\"') t++;
3968     if (*t == '\"') {
3969       t++;
3970       while (*t > 0 && *t != '\"') t++;
3971       if (*t == '\0') break;
3972       t++;
3973     }
3974 //    winerror(s);    // debugging only
3975     xargv[xargc] = s;
3976     xargc++;
3977     if (*t == '\0') break;
3978     *t = '\0';
3979     s = t+1;
3980   }
3981
3982 //  s = line;
3983 //  for (k = 0; k < xargc; k++) { /* create pointers to args */
3984 //    while (*s > '\0' && *s <= ' ') s++; /* eat white space */
3985 //    xargv[k] = s;
3986 //    s += strlen(s) +1;
3987 //  }
3988
3989 #ifdef DEBUGGING
3990   s = log_line;
3991   *s = '\0';
3992   for (k = 0; k < xargc; k++) {
3993     sprintf(s, "%d\t%s\n", k, xargv[k]);
3994     s += strlen(s);
3995   }
3996   winshow(log_line);
3997 #endif
3998   return xargc;
3999 }
4000
4001 // refers to TeXAsk in dviwindo.c
4002
4003 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
4004 int (* AskUserCall) (char *, char *, char *) = NULL;  // callback for user questions
4005
4006 // called from tex0.c only  ---  by initterm and term_input
4007
4008 //int ConsoleInput (char *question, char *buffer) 
4009 int ConsoleInput (char *question, char *help, char *buffer)
4010 {
4011   int ret=0;
4012 //  char *s;
4013   if (AskUserCall == NULL) return 0;
4014 //  sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
4015 //  show_line(log_line, 1);
4016
4017   *buffer = '\0';
4018   ret = AskUserCall (question, help, buffer);   // value returned by dialogbox
4019 //  strcpy(buffer, "x");
4020 //  strcat(buffer, " ");      // ???
4021 //  sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
4022 //  show_line(log_line, 1);
4023 //  input_line_finish();      // ???
4024 //  s = buffer + strlen(buffer);
4025 //  *s++ = ' ';           // space terminate
4026 //  *s++ = '\0';          // and null terminate
4027 //  returning != 0 means EOF or ^Z
4028   return ret;
4029 }
4030
4031 //  This is the new entry point of DLL called from DVIWindo 
4032 //  ARGS: console window to send messages to, command line, callback fun
4033 //  no console window output if hConsole is NULL
4034 //  returns -1 if it fails --- returns 0 if it succeeds
4035
4036 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
4037 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
4038 {
4039   int flag;
4040
4041   abort_flag = 0;            // redundant
4042   hConsoleWnd = NULL;         // redundant
4043
4044   AskUserCall = AskUser;        // remember callback
4045
4046   hConsoleWnd = hConsole;       // remember console window handle
4047
4048 //  can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
4049 //  if (grabenv("DEBUGPAUSE") != NULL) {
4050 //    show_line(line, 0);          // debugging - show command line
4051 //    show_line("\n", 0);
4052 //  }
4053
4054   xargc = makecommandargs(line);      // sets up global *xargv[]
4055
4056   if (xargc < 0) return -1;       // sanity check
4057
4058   if (hConsoleWnd != NULL) 
4059     SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
4060 //  SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
4061
4062
4063   (void) main(xargc, xargv);  // now run YandYTeX proper in texmf.c 
4064
4065   if (err_level > 0 || abort_flag > 0) {
4066 //    sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
4067 //        err_level, abort_flag);
4068 //    winerror(log_line);
4069   }
4070
4071 //  if (psbufpos > 0) sendpsbuffer(output);   // empty out PS buffer
4072 //  if (psbufpos > 0) PSputs("", output);   // output already closed
4073
4074   if (hConsoleWnd != NULL) {
4075     if (err_level > 0 || abort_flag > 0) flag = 1;
4076     else flag = 0;              // pass along error indication
4077     SendMessage(hConsoleWnd, ICN_DONE, flag, 0);  // flush out console buffer
4078   }
4079 //  PScallback = NULL;
4080   hConsoleWnd = NULL;
4081
4082   if (xargv != NULL) free(xargv);
4083   if (abort_flag) return -1;
4084   else return 0;
4085 }
4086
4087 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
4088 {
4089
4090   switch (fdwReason) {
4091     case DLL_PROCESS_ATTACH:
4092       // The DLL is being mapped into the process's address space
4093       // place to allocate memory ???
4094       // return FALSE if this fails
4095       hInstanceDLL = hInstDll;    /* remember it */
4096       break;
4097
4098     case DLL_THREAD_ATTACH:
4099       // A thread is being created
4100       break;
4101
4102     case DLL_THREAD_DETACH:
4103       // A thread is exiting cleanly
4104       break;
4105
4106     case DLL_PROCESS_DETACH:
4107       // The DLL is being unmapped from the process's address space
4108       // place to free any memory allocated
4109       // but make sure it in fact *was* allocated
4110       hInstanceDLL = NULL;    /* forget it */
4111       break;
4112   }
4113   return(TRUE); // used only for DLL_PROCESS_ATTACH
4114 }
4115 #endif  // end of new stuff for DLL version
4116
4117 //////////////////////////////////////////////////////////////////////////////
4118
4119
4120
4121 /*  NOTE: current_tfm = false (-c)
4122   not checking for TFM in current directory saves 0.1 sec
4123   (0.2 if file_method = false (-G) */
4124
4125 /*  NOTE: test_dir_access = false (-b):
4126   not checking whether readable file is a directory saves maybe 0.5 sec
4127   BUT only if file_method = false (-G) - otherwise its irrelevant */
4128
4129 /*  NOTE: dir_method = false (-D) --- method for checking whether directory
4130   using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4131   BUT not if current_tfm = false (-c) */
4132
4133 /*  NOTE: file_method = false (-G) --- method for checking file accessible
4134   using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4135
4136 /*  Fast flag combinations: nothing, bG, bcG, bcDG */
4137
4138 /* constants for _heapchk/_heapset/_heapwalk routines */
4139 /* #define _HEAPEMPTY (-1) */
4140 /* #define _HEAPOK  (-2) */
4141 /* #define _HEAPBADBEGIN  (-3) */
4142 /* #define _HEAPBADNODE (-4) */
4143 /* #define _HEAPEND (-5) */
4144 /* #define _HEAPBADPTR  (-6) */
4145
4146 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4147
4148 /* buffercopy no longer used */
4149
4150 /* To Knuthian reset right when command line interpreted */
4151