OSDN Git Service

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