OSDN Git Service

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