OSDN Git Service

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