OSDN Git Service

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