OSDN Git Service

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