OSDN Git Service

removed libmd5.
[putex/putex.git] / src / texsourc / local.c
1 /* Copyright 2007 TeX Users Group\r
2    Copyright 2014 Clerk Ma   \r
3 \r
4    This program is free software; you can redistribute it and/or modify\r
5    it under the terms of the GNU General Public License as published by\r
6    the Free Software Foundation; either version 2 of the License, or\r
7    (at your option) any later version.\r
8 \r
9    This program is distributed in the hope that it will be useful, but\r
10    WITHOUT ANY WARRANTY; without even the implied warranty of\r
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
12    General Public License for more details.\r
13 \r
14    You should have received a copy of the GNU General Public License\r
15    along with this program; if not, write to the Free Software\r
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
17    02110-1301 USA.  */\r
18 \r
19 #define EXTERN extern\r
20 \r
21 #include "yandytex.h"\r
22 \r
23 #define USEOUREALLOC\r
24 #define USEMEMSET\r
25 \r
26 #ifdef USEOUREALLOC\r
27   #define REALLOC ourrealloc\r
28 #else\r
29   #define REALLOC realloc\r
30 #endif\r
31 \r
32 #if   defined (__ANDROID__)\r
33   #define malloc_usable_size dlmalloc_usable_size\r
34 #elif defined (__APPLE__)\r
35   #define malloc_usable_size malloc_size\r
36 #endif\r
37 \r
38 #if   defined (__clang__)\r
39 const char * compiler = "Clang/LLVM";\r
40 #elif defined (__GNUC__) || defined(__GNUG__)\r
41 const char * compiler = "GCC";\r
42 #elif defined (_MSC_VER)\r
43 const char * compiler = "MSVC";\r
44 #endif\r
45 \r
46 #if   defined (_WIN64)\r
47 const char * dist = "Win64";\r
48 #elif defined (_WIN32)\r
49 const char * dist = "Win32";\r
50 #elif defined (__ANDROID__)\r
51 const char * dist = "Android";\r
52 #elif defined (__APPLE__)\r
53 const char * dist = "Darwin";\r
54 #elif defined (__gnu_linux__)\r
55 const char * dist = "Linux";\r
56 #else\r
57 const char * dist = "Unknown";\r
58 #endif\r
59 \r
60 const char * compiletime  = __TIME__;\r
61 const char * compiledate  = __DATE__;\r
62 const char * yandyversion = "2.3.0";\r
63 const char * application  = "Y&Y TeX";\r
64 const char * banner       = "This is TeX, Version 3.14159265";\r
65 \r
66 void print_banner (void)\r
67 {\r
68   char dist_ver[256];\r
69   memset(dist_ver, 0, sizeof(dist_ver));\r
70   sprintf(dist_ver, "%s (%s %s/%s)", banner, application, yandyversion, dist);\r
71   prints(dist_ver);\r
72 }\r
73 \r
74 clock_t start_time, main_time, finish_time;\r
75 \r
76 char * dvi_directory = "";\r
77 char * log_directory = "";\r
78 char * aux_directory = "";\r
79 char * fmt_directory = "";\r
80 char * pdf_directory = "";\r
81 \r
82 char log_line[256];\r
83 \r
84 boolean mem_spec_flag     = false;\r
85 boolean format_spec       = false;\r
86 boolean reorder_arg_flag  = true;  /* put command line flags/arguments first */\r
87 \r
88 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */\r
89 \r
90 unsigned char wintodos[128] =\r
91 {\r
92     0,   0,   0, 159,   0,   0,   0,   0,\r
93    94,   0,   0,   0,   0,   0,   0,   0,\r
94     0,  96,  39,   0,   0,   7,   0,   0,\r
95   126,   0,   0,   0,   0,   0,   0,   0,\r
96    32, 173, 189, 156, 207, 190, 221,  21,\r
97     0, 184, 166, 174, 170,  45, 169,   0,\r
98   248, 241, 253, 252,   0, 230,  20, 250,\r
99     0, 251, 167, 175, 172, 171, 243, 168,\r
100   183, 181, 182, 199, 142, 143, 146, 128,\r
101   212, 144, 210, 211, 222, 214, 215, 216,\r
102   209, 165, 227, 224, 226, 229, 153, 158,\r
103   157, 235, 233, 234, 154, 237, 232, 225,\r
104   133, 160, 131, 198, 132, 134, 145, 135,\r
105   138, 130, 136, 137, 141, 161, 140, 139,\r
106   208, 164, 149, 162, 147, 228, 148, 246,\r
107   155, 151, 163, 150, 129, 236, 231, 152\r
108 };\r
109 \r
110 void show_usage (void)\r
111 {\r
112   printf("\n"\r
113       "Useage: yandytex [OPTION]... [+format_file] [tex_file]\n\n"\r
114       "--help       -?  show this usage summary\n"\r
115       "--initex     -i  start up as initex (create format file)\n"\r
116       "--verbose    -v  be verbose (show implementation version number)\n"\r
117       "--ascii      -n  do not allow `non ASCII' characters in input files\n"\r
118       "                    (complain instead)\n"\r
119       "--showhex    -w  do not show `non ASCII' characters in hexadecimal\n"\r
120       "                    (show as is)\n"\r
121       "--nodos      -d  do not allow DOS style file names - i.e. do not convert\n"\r
122       "                    \\ to /\n"\r
123       "--nomac      -r  do not allow Mac style termination - i.e. do not convert\n"\r
124       "                    \\r to \\n\n"\r
125       "--patterns   -p  allow use of \\patterns after loading format (initex only)\n"\r
126       "--knuthify   -K  disable all extensions to basic TeX\n"\r
127       "--main-mem   -m  initial main memory size in kilo words (initex only)\n"\r
128       "--hyph-size  -e  hyphenation exception dictionary size (initex only)\n"\r
129       "--trie-size  -h  hyphenation pattern trie size (initex only)\n"\r
130       "--xchr-file  -x  use `non ASCII' character mapping (xchr[]) defined in file\n"\r
131       "--key-file   -k  use `key replacement' defined in file\n"\r
132       "--dvi-dir    -o  write DVI file in specified directory (default '.')\n"\r
133       "--log-dir    -l  write LOG file in specified directory (default '.')\n"\r
134       "--aux-dir    -a  write AUX file in specified directory (default '.')\n");\r
135   uexit(EXIT_FAILURE);\r
136 }\r
137 \r
138 // Sep 27 1990 => 1990 Sep 27\r
139 // 0123456789     0123456789\r
140 void scivilize (char * date)\r
141 {\r
142   int k;\r
143   char pyear[6];\r
144 \r
145   strcpy(pyear, date + 7);\r
146 \r
147   for (k = 5; k >= 0; k--)\r
148     date[k + 5] = date[k];\r
149 \r
150   for (k = 0; k < 4; k++)\r
151     date[k] = pyear[k];\r
152 \r
153   date[4] = ' ';\r
154 \r
155   if (date[9] == ' ')\r
156     date[9] = '0';\r
157 }\r
158 \r
159 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35\r
160 void lcivilize (char * date)\r
161 {\r
162   int k;\r
163   char pyear[6];\r
164 \r
165   strcpy(pyear, date + 20);\r
166 \r
167   for (k = 18; k >= 0; k--)\r
168     date[k + 1] = date[k];\r
169 \r
170   date[20] = '\0';\r
171 \r
172   for (k = 0; k < 4; k++)\r
173     date[k] = pyear[k];\r
174 \r
175   date[4] = ' ';\r
176 }\r
177 \r
178 void stamp_it (char * s)\r
179 {\r
180   char date[11 + 1];\r
181 \r
182   strcpy(date, compiledate);\r
183   scivilize(date);\r
184   sprintf(s, "%s %s (compiled time: %s %s with %s)",\r
185     application, yandyversion, date, compiletime, compiler);\r
186   s += strlen(s);\r
187 }\r
188 \r
189 #define MAXCHRS 256\r
190 #define NOTDEF  127\r
191 \r
192 void read_xchr_sub (FILE * xchr_input)\r
193 {\r
194   char buffer[file_name_size];\r
195   int k, from, to, count = 0;\r
196   char * s;\r
197 \r
198   memset(xchr, NOTDEF, MAXCHRS);\r
199   memset(xord, NOTDEF, MAXCHRS);\r
200 \r
201 #ifdef ALLOCATEBUFFER\r
202   while (fgets(buffer, current_buf_size, xchr_input) != NULL)\r
203 #else\r
204   while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)\r
205 #endif\r
206   {\r
207     if (*buffer == '%' || *buffer == ';' || *buffer == '\n')\r
208       continue;\r
209 \r
210     from = (int) strtol (buffer, &s, 0);\r
211     to = (int) strtol (s, NULL, 0);\r
212 \r
213     if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)\r
214     {\r
215       if (xchr[from] == NOTDEF)\r
216         xchr[from] = (unsigned char) to;\r
217       else\r
218         printf("NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);\r
219 \r
220       if (xord[to] == NOTDEF)\r
221         xord[to] = (unsigned char) from;\r
222       else\r
223         printf("NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);\r
224 \r
225       count++;\r
226     }\r
227   }\r
228 \r
229   for (k = 0; k < MAXCHRS; k++)\r
230   {\r
231     if (xchr[k] == NOTDEF)   /* if it has not been filled */\r
232     {\r
233       if (xord[k] == NOTDEF) /* see whether used already */\r
234       {\r
235         xchr[k] = (unsigned char) k; /* no, so make identity */\r
236         xord[k] = (unsigned char) k; /* no, so make identity */\r
237       }\r
238     }\r
239   }\r
240 \r
241   xchr[NOTDEF] = NOTDEF;         /* fixed point of mapping */\r
242 \r
243   if (trace_flag)\r
244   {\r
245     printf("Read %d xchr[] pairs:\n", count);\r
246 \r
247     for (k = 0; k < MAXCHRS; k++)\r
248     {\r
249       if (xchr[k] != NOTDEF)\r
250         printf("%d => %d\n", k, xchr[k]);\r
251     }\r
252   }\r
253 }\r
254 \r
255 char * replacement[MAXCHRS];     /* pointers to replacement strings */\r
256 \r
257 void read_repl_sub (FILE * repl_input)\r
258 {\r
259   int k, n, m, chrs;\r
260   char buffer[file_name_size];\r
261   char charname[128];\r
262   int charnum[10];\r
263   char * s, * t;\r
264   \r
265   memset(replacement, 0, MAXCHRS * sizeof(replacement[0]));\r
266 \r
267   while (fgets(buffer, file_name_size, repl_input) != NULL)\r
268   {\r
269     if (*buffer == '%' || *buffer == ';' || *buffer == '\n')\r
270       continue;\r
271 \r
272     if ((m = sscanf(buffer, "%d%n %s", &chrs, &n, (char *)&charname)) == 0)\r
273       continue;\r
274     else if (m == 2)\r
275     {\r
276       if (*charname == '"')   /* deal with quoted string "..." */\r
277       {\r
278         s = buffer + n;\r
279         t = charname;\r
280 \r
281         while (*s != '"' && *s != '\0')\r
282           s++;  /* step up to " */\r
283 \r
284         if (*s++ == '\0')\r
285           continue;       /* sanity check */\r
286 \r
287         while (*s != '\0')\r
288         {\r
289           if (*s == '"')\r
290           {\r
291             s++;            /* is it "" perhaps ? */\r
292 \r
293             if (*s != '"')\r
294               break;   /* no, end of string */\r
295           }\r
296 \r
297           *t++ = *s++;          /* copy over */\r
298         }\r
299 \r
300         *t = '\0';              /* and terminate */\r
301       }\r
302 \r
303       if (chrs >= 0 && chrs < MAXCHRS)\r
304         replacement[chrs] = xstrdup(charname);\r
305     }\r
306 /*    presently the following can never get triggered */\r
307 /*    which is good, because it is perhaps not right ... */\r
308     else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",\r
309       &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,\r
310         charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {\r
311 /*      for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */\r
312       for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];\r
313       charname[m] = '\0';\r
314       if (chrs >= 0 && chrs < MAXCHRS)\r
315         replacement[chrs] = xstrdup(charname);      \r
316     }\r
317     else\r
318       printf("ERROR: don't understand %s", buffer);\r
319   }\r
320 \r
321   if (trace_flag)\r
322   {\r
323     puts("Key replacement table");\r
324 \r
325     for (k = 0; k < MAXCHRS; k++)\r
326     {\r
327       if (replacement[k] != NULL)\r
328         printf("%d\t%s\n", k, replacement[k]);\r
329     }\r
330   }\r
331 }\r
332 \r
333 /* Following used both to read xchr[] file and key replacement file */\r
334 /* the flag is 0 for -x=... and the flag is 1 for -k=... */\r
335 int read_xchr_file (char *filename, int flag, char *argv[])\r
336 {\r
337   FILE *xchr_input;\r
338   char infile[file_name_size];\r
339   char *s;\r
340 \r
341   if (filename == NULL)\r
342     return -1;\r
343 \r
344   if (trace_flag)\r
345     printf("Reading xchr/repl %s\n", filename);\r
346 \r
347   /* first try using file as specified */\r
348   strcpy(infile, filename);\r
349 \r
350   if (trace_flag)\r
351     printf("Trying %s\n", infile);\r
352 \r
353   xchr_input = fopen (infile, "r");\r
354 \r
355   if (xchr_input == NULL)\r
356   {\r
357     if (strrchr(infile, '.') == NULL)\r
358     {\r
359       if (flag == 0)\r
360         strcat(infile, ".map");\r
361       else\r
362         strcat(infile, ".key");\r
363 \r
364       if (trace_flag)\r
365         printf("Trying %s\n", infile);\r
366       \r
367       xchr_input = fopen(infile, "r");\r
368     }\r
369   }\r
370 \r
371   if (xchr_input == NULL)\r
372   {\r
373     strcpy(infile, argv[0]);     /* try TeX program path */\r
374 \r
375     if ((s = strrchr (infile, '\\')) != NULL)\r
376       *(s+1) = '\0';\r
377     else if ((s = strrchr (infile, '/')) != NULL)\r
378       *(s+1) = '\0';\r
379     else if ((s = strrchr (infile, ':')) != NULL)\r
380       *(s+1) = '\0';\r
381 \r
382     strcat (infile, filename);\r
383 \r
384     if (trace_flag)\r
385       printf("Trying %s\n", infile);\r
386 \r
387     xchr_input = fopen (infile, "r");\r
388 \r
389     if (xchr_input == NULL)\r
390     {\r
391       if (strchr(infile, '.') == NULL)\r
392       {\r
393         if (flag == 0)\r
394           strcat(infile, ".map");\r
395         else\r
396           strcat(infile, ".key");\r
397 \r
398         if (trace_flag)\r
399           printf("Trying %s\n", infile);\r
400 \r
401         xchr_input = fopen (infile, "r");\r
402       }\r
403     }\r
404   }\r
405 \r
406   if (xchr_input == NULL)\r
407   {\r
408     strcpy(infile, argv[0]);     /* try TeX program path */\r
409 \r
410     if ((s = strrchr (infile, '\\')) != NULL)\r
411       *(s + 1) = '\0';\r
412     else if ((s = strrchr (infile, '/')) != NULL)\r
413       *(s + 1) = '\0';\r
414     else if ((s = strrchr (infile, ':')) != NULL)\r
415       *(s + 1) = '\0';\r
416 \r
417     strcat(infile, "keyboard\\");\r
418     strcat(infile, filename);\r
419 \r
420     if (trace_flag)\r
421       printf("Trying %s\n", infile);\r
422 \r
423     xchr_input = fopen (infile, "r");\r
424 \r
425     if (xchr_input == NULL)\r
426     {\r
427       if (strchr(infile, '.') == NULL)\r
428       {\r
429         if (flag == 0)\r
430           strcat(infile, ".map");\r
431         else\r
432           strcat(infile, ".key");\r
433 \r
434         if (trace_flag)\r
435           printf("Trying %s\n", infile);\r
436 \r
437         xchr_input = fopen (infile, "r");\r
438       }\r
439     }\r
440   }\r
441 \r
442   /* Note: can't look in TeX source file dir, since that is not known yet */\r
443   if (xchr_input == NULL)\r
444   {\r
445     printf("ERROR: Sorry, cannot find %s file %s",\r
446         flag ? " xchr[]" : "key mapping", filename);\r
447     perrormod (filename);\r
448     return 0;\r
449   }\r
450 \r
451   if (flag == 0)\r
452     read_xchr_sub(xchr_input);\r
453   else\r
454     read_repl_sub(xchr_input);\r
455 \r
456   (void) fclose(xchr_input);\r
457 \r
458   return 1;\r
459 }\r
460 \r
461 /* need to also set `key_replace' here based on command line */\r
462 /* need to also allocate `buffercopy' here and free at end */\r
463 /* need to call `readreplace' in appropriate place */\r
464 \r
465 #define MAXSPLITS 3\r
466 \r
467 /* ad hoc default minimum growth in memory realloc is 62% */\r
468 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */\r
469 int percent_grow    = 62; /* default minimum growth in memory realloc is 62% */\r
470 int total_allocated = 0;  /* total memory allocated so far */\r
471 int ini_max_address = 0;  /* maximum address when starting */\r
472 int max_address     = 0;  /* maximum address seen in allocated memory */\r
473 \r
474 \r
475 void show_maximums (FILE * output)\r
476 {\r
477   sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);\r
478   fputs(log_line, output);\r
479 }\r
480 \r
481 /* our own version of realloc --- avoid supposed MicroSoft version bug */\r
482 /* also tries _expand first, which can avoid address growth ... */\r
483 \r
484 #ifdef USEOUREALLOC \r
485 void * ourrealloc (void * old, size_t new_size)\r
486 {\r
487   void * mnew;\r
488   size_t old_size, overlap;\r
489   \r
490   /* round up to nearest multiple of four bytes */\r
491   /* avoid unlikely alignment */\r
492   if ((new_size % 4) != 0)\r
493     new_size = ((new_size / 4) + 1) * 4;\r
494 \r
495   if (old == NULL)\r
496     return malloc (new_size);  /* no old block - use malloc */\r
497 \r
498 #ifdef _WIN32\r
499   old_size = _msize (old);\r
500 #else\r
501   old_size = malloc_usable_size (old);\r
502 #endif\r
503 \r
504   if (old_size >= new_size && old_size < new_size + 4)\r
505     return old;\r
506 \r
507 #ifdef _WIN32\r
508   mnew = _expand (old, new_size); /* first try and expand in place MSVC */\r
509 #else\r
510   mnew = realloc (old, new_size);\r
511 #endif\r
512 \r
513   if (mnew != NULL)\r
514   {\r
515     if (trace_flag)\r
516       printf("EXPANDED! %p (%ld) == %p (%ld)\n",\r
517           mnew, new_size, old, old_size);\r
518 \r
519     return mnew;\r
520   }\r
521 \r
522   /* do this if you want to call the real realloc next -  */\r
523   mnew = realloc (old, new_size);\r
524 \r
525   if (mnew != NULL)\r
526     return mnew;\r
527 \r
528   /*  we are screwed typically if we ever drop through here - no more space */\r
529   mnew = malloc (new_size); /* otherwise find new space */\r
530 \r
531   if (mnew == NULL)\r
532     return mnew;        /* if unable to allocate */\r
533 \r
534   if (old_size < new_size)\r
535     overlap = old_size;\r
536   else\r
537     overlap = new_size;\r
538 \r
539   memcpy (mnew, old, overlap); /* copy old data to new area */\r
540   free(old); /* free the old area */\r
541 \r
542   return mnew;\r
543 }\r
544 #endif\r
545 \r
546 void memory_error (const char * s, int n)\r
547 {\r
548   if (log_opened)\r
549   {\r
550     fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);\r
551     show_maximums(log_file);\r
552   }\r
553 \r
554   printf("\n! Unable to allocate %d bytes for %s\n", n, s);\r
555   show_maximums(stderr);\r
556 }\r
557 \r
558 void trace_memory (const char * s, int n)\r
559 {\r
560   printf("Allocating %d bytes for %s\n", n, s);\r
561 }\r
562 \r
563 void update_statistics (long address, int size, int old_size)\r
564 {\r
565   if (address + size > max_address)\r
566     max_address = address + size;\r
567 \r
568   total_allocated =  total_allocated + size - old_size;\r
569 }\r
570 \r
571 void probe_memory (void)\r
572 {\r
573   char * s = (char *) malloc(sizeof(void *));\r
574   free(s);\r
575   update_statistics ((long) s, 0, 0);\r
576 }\r
577 \r
578 void probe_show (void)\r
579 {\r
580   probe_memory();\r
581   show_maximums(stdout);\r
582 }\r
583 \r
584 size_t roundup (size_t n)\r
585 {\r
586   if ((n % sizeof(void *)) == 0)\r
587     return n;\r
588   else\r
589     return ((n / sizeof(void *)) + 1) * sizeof(void *);\r
590 }\r
591 \r
592 #ifdef ALLOCATETRIES\r
593 /* returns -1 if it fails */\r
594 \r
595 int allocate_tries (int trie_max)\r
596 {\r
597   int n, nl, no, nc;\r
598 \r
599   if (trie_max > 1000000)\r
600     trie_max = 1000000;\r
601 \r
602   nl = (trie_max + 1) * sizeof(halfword);\r
603   no = (trie_max + 1) * sizeof(halfword);\r
604   nc = (trie_max + 1) * sizeof(quarterword);\r
605   n = nl + no + nc;\r
606 \r
607   if (trace_flag)\r
608     trace_memory("hyphen trie", n);\r
609 \r
610   trie_trl = (halfword *) malloc(roundup(nl));\r
611   trie_tro = (halfword *) malloc(roundup(no));\r
612   trie_trc = (quarterword *) malloc(roundup(nc));\r
613 \r
614   if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)\r
615   {\r
616     memory_error("hyphen trie", n);\r
617     return -1;\r
618   }\r
619 \r
620   if (trace_flag)\r
621     printf("Addresses trie_trl %p trie_tro %p trie_trc %p\n", trie_trl, trie_tro, trie_trc);\r
622 \r
623   update_statistics((long) trie_trl, nl, 0);\r
624   update_statistics((long) trie_tro, no, 0);\r
625   update_statistics((long) trie_trc, nc, 0);\r
626 \r
627   trie_size = trie_max;\r
628 \r
629   if (trace_flag)\r
630     probe_show();\r
631 \r
632   return 0; // success\r
633 }\r
634 #endif\r
635 \r
636 #ifdef ALLOCATEHYPHEN\r
637 int current_prime = 0; /* remember in case reallocated later */\r
638 \r
639 /* we don't return an address here, since TWO memory regions allocated */\r
640 /* plus, we don't really reallocate, we FLUSH the old information totally */\r
641 /* returns -1 if it fails */\r
642 \r
643 int realloc_hyphen (int hyphen_prime)\r
644 {\r
645   int n, nw, nl;\r
646 \r
647   if (!prime(hyphen_prime))\r
648   {\r
649     printf("ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);\r
650     return -1;\r
651   }\r
652 \r
653 /*  need not/cannot preserve old contents when hyphen prime is changed */\r
654 /*  if (hyph_list != NULL) free(hyph_list); */\r
655 /*  if (hyph_word != NULL) free(hyph_word); */\r
656   nw = (hyphen_prime + 1) * sizeof(str_number);\r
657   nl = (hyphen_prime + 1) * sizeof(halfword);\r
658   n = nw + nl;\r
659 \r
660   if (trace_flag)\r
661     trace_memory("hyphen exception", n);\r
662 \r
663   hyph_word = (str_number *) REALLOC (hyph_word, nw);\r
664   hyph_list = (halfword *) REALLOC (hyph_list, nl);\r
665 \r
666   if (hyph_word == NULL || hyph_list == NULL)\r
667   {\r
668     memory_error("hyphen exception", n);\r
669     return -1;\r
670   }\r
671 \r
672   if (trace_flag)\r
673     printf("Addresses hyph_word %p hyph_list %p\n", hyph_word, hyph_list);\r
674 \r
675 /*  cannot preserve old contents when hyphen prime is changed */\r
676 #ifdef USEMEMSET\r
677   memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));\r
678 #else\r
679   for (k = 0; k <= hyphen_prime; k++)\r
680     hyph_word[k]= 0;\r
681 #endif\r
682 \r
683 #ifdef USEMEMSET\r
684   memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));\r
685 #else\r
686   for (k = 0; k <= hyphen_prime; k++)\r
687     hyph_list[k]= 0;\r
688 #endif\r
689 \r
690   hyph_count = 0;\r
691 \r
692   if (current_prime != 0)\r
693   {\r
694     update_statistics((long) hyph_word, nw, (current_prime + 1) * sizeof(str_number));\r
695     update_statistics((long) hyph_list, nl, (current_prime + 1) * sizeof(halfword));\r
696   }\r
697   else\r
698   {\r
699     update_statistics((long) hyph_word, nw, 0);\r
700     update_statistics((long) hyph_list, nl, 0);\r
701   }\r
702 \r
703   current_prime = hyphen_prime;\r
704 \r
705   if (trace_flag)\r
706     probe_show();\r
707 \r
708   return 0; // success\r
709 }\r
710 #endif\r
711 \r
712 int current_mem_size = 0;   /* current total words in main mem allocated -1 */\r
713 \r
714 /* this gets called from itex.c when it figures out what mem_top is */\r
715 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */\r
716 /* initial allocation only, may get expanded later */\r
717 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */\r
718 /* returns NULL if it fails */\r
719 \r
720 #ifdef ALLOCATEMAIN   \r
721 /* initial main memory alloc - mem_top */\r
722 memory_word * allocate_main_memory (int size)\r
723 {\r
724   int n;\r
725 \r
726   if (main_memory != NULL)\r
727   {\r
728     if (trace_flag)\r
729       puts("Reallocating initial memory allocation");\r
730   }\r
731 \r
732   mem_top = mem_bot + size;\r
733   mem_max = mem_top;\r
734   mem_start = 0;     /* bottom of memory allocated by system */\r
735   mem_min = 0;       /* bottom of area made available to TeX */\r
736   n = (mem_max - mem_start + 1) * sizeof (memory_word);\r
737 \r
738   if (trace_flag)\r
739     trace_memory("main memory", n);\r
740 \r
741   main_memory = (memory_word *) REALLOC (main_memory, n);\r
742 \r
743   if (main_memory == NULL)\r
744   {\r
745     memory_error("initial main memory", n);\r
746     return NULL;\r
747   }\r
748 \r
749   if (trace_flag)\r
750     printf("Address main memory == %p\n", main_memory);\r
751 \r
752   mem = main_memory;\r
753 \r
754   if (mem_start != 0 && !is_initex)\r
755     mem = main_memory - mem_start;\r
756 \r
757   if (trace_flag)\r
758     printf("Offset address main memory == %p\n", mem);\r
759 \r
760   update_statistics((long) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));\r
761 /*  current_mem_size = (mem_max - mem_start + 1); */\r
762   current_mem_size = mem_max - mem_start;   /* total number of words - 1 */\r
763 \r
764   if (trace_flag)\r
765     probe_show();\r
766 \r
767   return mem;\r
768 }\r
769 #endif\r
770 \r
771 #ifdef ALLOCATEMAIN\r
772 /* int firstallocation = 1; */\r
773 \r
774 /* increase main memory allocation at low end and high end */\r
775 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */\r
776 /* returns NULL if it fails */\r
777 \r
778 memory_word * realloc_main (int lo_size, int hi_size)\r
779 {  \r
780   int k, min_size;\r
781   int new_size = 0;\r
782   int n = 0;\r
783   memory_word * new_memory = NULL;\r
784 \r
785   if (trace_flag)\r
786     printf("WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);\r
787 \r
788   if (is_initex)\r
789   {\r
790     puts("ERROR: Cannot extent main memory in initex");\r
791 \r
792     if (!knuth_flag)\r
793       puts("Please use `-m=...' on command line");\r
794 \r
795     return NULL;\r
796   }\r
797 \r
798   if (trace_flag)\r
799     printf("Old Address %s == %p\n", "main memory", main_memory);\r
800 \r
801   /* if we REALLY run up to limit ! */\r
802   if (current_mem_size + 1 == max_mem_size)\r
803   {\r
804     memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));\r
805     return NULL;\r
806   }\r
807 \r
808 /*  first allocation should expand *both* lo and hi */\r
809   if (hi_size == 0 && mem_end == mem_max)\r
810     hi_size = lo_size;\r
811 \r
812   if (lo_size == 0 && mem_start == mem_min)\r
813     lo_size = hi_size;\r
814 \r
815 /*  try and prevent excessive frequent reallocations */\r
816 /*  while avoiding over allocation by too much */\r
817   min_size = current_mem_size / 100 * percent_grow;\r
818 \r
819   if (lo_size + hi_size < min_size)\r
820   {\r
821     if (lo_size > 0 && hi_size > 0)\r
822     {\r
823       lo_size = min_size / 2;\r
824       hi_size = min_size / 2;\r
825     }\r
826     else if (lo_size > 0)\r
827       lo_size = min_size;\r
828     else if (hi_size > 0)\r
829       hi_size = min_size;\r
830   }\r
831 \r
832   if (lo_size > 0 && lo_size < mem_top / 2)\r
833     lo_size = mem_top / 2;\r
834 \r
835   if (hi_size > 0 && hi_size < mem_top / 2)\r
836     hi_size = mem_top / 2;\r
837 \r
838   for (k = 0; k < MAXSPLITS; k++)\r
839   {\r
840     new_size = current_mem_size + lo_size + hi_size;\r
841 \r
842     if (new_size >= max_mem_size) /* bump against limit - ha ha ha */\r
843     {\r
844       while (new_size >= max_mem_size)\r
845       {\r
846         lo_size = lo_size / 2;\r
847         hi_size = hi_size / 2;\r
848         new_size = current_mem_size + lo_size + hi_size;\r
849       }\r
850     }\r
851 \r
852     n = (new_size + 1) * sizeof (memory_word);\r
853 \r
854     if (trace_flag)\r
855       trace_memory("main memory", n);\r
856 \r
857     new_memory = (memory_word *) REALLOC (main_memory, n);\r
858 \r
859     if (new_memory != NULL)\r
860       break; /* did we get it ? */\r
861 \r
862     if (current_mem_size == 0)\r
863       break; /* in case we ever use for initial */\r
864 \r
865     lo_size = lo_size / 2; hi_size = hi_size / 2;\r
866   }\r
867 \r
868   if (new_memory == NULL)\r
869   {\r
870     memory_error("main memory", n);\r
871     return mem;\r
872   }\r
873 \r
874   if (trace_flag)\r
875     printf("New Address %s == %p\n", "main memory", new_memory);\r
876 \r
877   if (lo_size > 0)\r
878   {\r
879 /*  shift everything upward to make space for new low area */\r
880     if (trace_flag)\r
881       printf("memmove %p %p %ld \n", new_memory + lo_size,\r
882           new_memory, (current_mem_size + 1) * sizeof(memory_word));\r
883 \r
884     memmove (new_memory + lo_size, new_memory,\r
885       (current_mem_size + 1) * sizeof(memory_word));\r
886 /*  could reduce words moved by (mem_max - mem_end) */\r
887   }\r
888 \r
889   main_memory = new_memory;       /* remember for free later */\r
890 \r
891   if (lo_size > 0)\r
892     mem_start = mem_start - lo_size; /* update lower limit */\r
893 \r
894   if (hi_size > 0)\r
895     mem_max = mem_max + hi_size;   /* update upper limit */\r
896 \r
897   update_statistics ((long) main_memory, n,\r
898     (current_mem_size + 1) * sizeof (memory_word));\r
899   current_mem_size = new_size;\r
900 \r
901   if (current_mem_size != mem_max - mem_start)\r
902     puts("ERROR: Impossible Memory Error");\r
903 \r
904   if (mem_start != 0)\r
905     mem = main_memory - mem_start;\r
906   else\r
907     mem = main_memory;\r
908 \r
909   if (trace_flag)\r
910     probe_show();\r
911 \r
912   return mem;\r
913 }\r
914 #endif\r
915 \r
916 #ifdef ALLOCATEFONT\r
917 int current_font_mem_size = 0;\r
918 \r
919 memory_word * realloc_font_info (int size)\r
920 {\r
921   memory_word * new_font_info = NULL;\r
922   int k, min_size;\r
923   int new_size = 0;\r
924   int n = 0;\r
925 \r
926   if (trace_flag)\r
927     printf("Old Address %s == %p\n", "font_info", font_info);\r
928 \r
929   /* during initial allocation, font_info == NULL - realloc acts like malloc */\r
930   /* during initial allocation current_font_mem_size == 0 */\r
931   if (current_font_mem_size == font_mem_size)  /* if we REALLY run up to limit */\r
932   {\r
933     /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */\r
934     return font_info;    /* pass it back to TeX 99/Fabe/4 */\r
935   }\r
936   /* try and prevent excessive frequent reallocations */\r
937   /* while avoiding over allocation by too much */\r
938   /* min_size = current_font_mem_size / 2; */\r
939   min_size = current_font_mem_size / 100 * percent_grow;\r
940 \r
941   if (size < min_size)\r
942     size = min_size;\r
943 \r
944   if (size < initial_font_mem_size)\r
945     size = initial_font_mem_size;\r
946 \r
947   for (k=0; k < MAXSPLITS; k++)\r
948   {\r
949     new_size = current_font_mem_size + size;\r
950 \r
951     if (new_size > font_mem_size)\r
952       new_size = font_mem_size; /* bump against limit */\r
953 \r
954 /*    important + 1 since fmemoryword font_info[font_mem_size + 1]  original */\r
955     n = (new_size + 1) * sizeof (memory_word);\r
956 \r
957     if (trace_flag)\r
958       trace_memory("font_info", n);\r
959 \r
960     new_font_info = (memory_word *) REALLOC (font_info, n);\r
961 \r
962     if (new_font_info != NULL)\r
963       break;   /* did we get it ? */\r
964 \r
965     if (current_font_mem_size == 0)\r
966       break; /* initial allocation must work */\r
967 \r
968     size = size / 2;\r
969   }\r
970 \r
971   if (new_font_info == NULL)\r
972   {\r
973     memory_error("font", n);\r
974     return font_info;        /* try and continue !!! */\r
975   }\r
976 \r
977   font_info = new_font_info;\r
978 \r
979   if (trace_flag)\r
980     printf("New Address %s == %p\n", "font_info", font_info);\r
981 \r
982   update_statistics ((long) font_info, n, current_font_mem_size * sizeof(memory_word));\r
983   current_font_mem_size = new_size;\r
984 \r
985   if (trace_flag)\r
986     probe_show();\r
987 \r
988   return font_info;\r
989 }\r
990 #endif\r
991 \r
992 #ifdef ALLOCATESTRING\r
993 int current_pool_size = 0;\r
994 \r
995 packed_ASCII_code * realloc_str_pool (int size)\r
996 {\r
997   int k, min_size;\r
998   int new_size = 0;\r
999   int n = 0;\r
1000   packed_ASCII_code * new_str_pool = NULL;\r
1001 \r
1002   if (trace_flag)\r
1003     printf("Old Address %s == %p\n", "string pool", str_pool);\r
1004 \r
1005   if (current_pool_size == pool_size)\r
1006   {\r
1007 /*    memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */\r
1008 /*    exit (1); */\r
1009     return str_pool;   /* pass it back to TeX 99/Fabe/4 */\r
1010   }\r
1011 \r
1012   min_size =  current_pool_size / 100 * percent_grow;\r
1013 \r
1014   if (size < min_size)\r
1015     size = min_size;\r
1016 \r
1017   if (size < initial_pool_size)\r
1018     size = initial_pool_size;\r
1019 \r
1020   for (k = 0; k < MAXSPLITS; k++)\r
1021   {\r
1022     new_size = current_pool_size + size;\r
1023 \r
1024     if (new_size > pool_size)\r
1025       new_size = pool_size;\r
1026 /* important + 1 since  packed_ASCII_code str_pool[pool_size + 1]; in original */\r
1027     n = (new_size + 1) * sizeof (packed_ASCII_code);\r
1028 \r
1029     if (trace_flag)\r
1030       trace_memory("str_pool", n);\r
1031 \r
1032     new_str_pool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */\r
1033 \r
1034     if (new_str_pool != NULL)\r
1035       break;    /* did we get it ? */\r
1036 \r
1037     if (current_pool_size == 0)\r
1038       break;  /* initial allocation must work */\r
1039 \r
1040     size = size / 2;          /* else can retry smaller */\r
1041   }\r
1042 \r
1043   if (new_str_pool == NULL)\r
1044   {\r
1045     memory_error("string pool", n);\r
1046     return str_pool;           /* try and continue !!! */\r
1047   }\r
1048 \r
1049   str_pool = new_str_pool;\r
1050   update_statistics ((long) str_pool, n, current_pool_size);\r
1051   current_pool_size = new_size;\r
1052 \r
1053   if (trace_flag)\r
1054     printf("New Address %s == %p\n", "string pool", str_pool);\r
1055   \r
1056   if (trace_flag)\r
1057     probe_show();\r
1058 \r
1059   return str_pool;\r
1060 }\r
1061 #endif\r
1062 \r
1063 #ifdef ALLOCATESTRING\r
1064 int current_max_strings = 0;\r
1065 \r
1066 pool_pointer * realloc_str_start (int size)\r
1067 {\r
1068   int k, min_size;\r
1069   int n = 0;\r
1070   int new_size = 0;\r
1071   pool_pointer * new_str_start = NULL;\r
1072 \r
1073   if (trace_flag)\r
1074     printf("Old Address %s == %p\n", "string start", str_start);\r
1075 \r
1076   if (current_max_strings == max_strings)\r
1077   {\r
1078 /*    memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */\r
1079 /*    exit (1); */\r
1080     return str_start;    /* pass it back to TeX 99/Fabe/4 */\r
1081   }\r
1082 \r
1083   min_size = current_max_strings / 100 * percent_grow;\r
1084 \r
1085   if (size < min_size)\r
1086     size = min_size;\r
1087 \r
1088   if (size < initial_max_strings)\r
1089     size = initial_max_strings;\r
1090 \r
1091   for (k = 0; k < MAXSPLITS; k++)\r
1092   {\r
1093     new_size = current_max_strings + size;\r
1094 \r
1095     if (new_size > max_strings)\r
1096       new_size = max_strings;\r
1097 /*    important + 1 since str_start[maxstring + 1] originally */\r
1098     n = (new_size + 1) * sizeof (pool_pointer);\r
1099 \r
1100     if (trace_flag)\r
1101       trace_memory("str_start", n);\r
1102 \r
1103     new_str_start = (pool_pointer *) REALLOC (str_start, n);\r
1104 \r
1105     if (new_str_start != NULL)\r
1106       break;   /* did we get it ? */\r
1107 \r
1108     if (current_max_strings == 0)\r
1109       break;  /* initial allocation must work */\r
1110 \r
1111     size = size / 2;          /* otherwise can try smaller */\r
1112   }\r
1113 \r
1114   if (new_str_start == NULL)\r
1115   {\r
1116     memory_error("string pointer", n);\r
1117     return str_start;          /* try and continue */\r
1118   }\r
1119 \r
1120   str_start = new_str_start;\r
1121   update_statistics((long) str_start, n, current_max_strings * sizeof (pool_pointer));\r
1122   current_max_strings = new_size;\r
1123 \r
1124   if (trace_flag)\r
1125     printf("New Address %s == %p\n", "string start", str_start);\r
1126 \r
1127   if (trace_flag)\r
1128     probe_show();\r
1129 \r
1130   return str_start;\r
1131 }\r
1132 #endif\r
1133 \r
1134 #ifdef ALLOCATEINI\r
1135 /* returns -1 if it fails */\r
1136 /* size == trie_size */\r
1137 int allocate_ini (int size)\r
1138 {\r
1139   int n, nl, no, nc, nr, nh, nt;\r
1140 \r
1141   nh = (size + 1) * sizeof(trie_pointer);\r
1142   nr = (size + 1) * sizeof(trie_pointer);\r
1143   nl = (size + 1) * sizeof(trie_pointer);\r
1144   no = (size + 1) * sizeof(trie_op_code);\r
1145   nc = (size + 1) * sizeof(packed_ASCII_code);\r
1146   nt = (size + 1) * sizeof(char);\r
1147   n = nl + no + nc + nr + nh + nt;\r
1148 \r
1149   if (trace_flag)\r
1150     trace_memory ("initex hyphen trie", n);\r
1151 \r
1152   trie_l = (trie_pointer *) malloc (roundup(nl));\r
1153   trie_o = (trie_op_code *) malloc (roundup(no));\r
1154   trie_c = (packed_ASCII_code *) malloc (roundup(nc));\r
1155   trie_r = (trie_pointer *) malloc (roundup(nr));\r
1156   trie_hash = (trie_pointer *) malloc (roundup(nh));\r
1157   trie_taken = (char *) malloc (roundup(nt));\r
1158   \r
1159   if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||\r
1160       trie_hash == NULL || trie_taken == NULL)\r
1161   {\r
1162     memory_error("initex hyphen trie", n);\r
1163     return -1;\r
1164   }\r
1165   \r
1166   if (trace_flag)\r
1167   {\r
1168     printf("Addresses: trie_l %p trie_o %p trie_c %p\n", trie_l, trie_o, trie_c);\r
1169     printf("Addresses: trie_r %p trie_hash %p trie_taken %p\n", trie_r, trie_hash, trie_taken);\r
1170   }\r
1171 \r
1172   update_statistics ((long) trie_l, nl, 0);\r
1173   update_statistics ((long) trie_o, no, 0);\r
1174   update_statistics ((long) trie_c, nc, 0);\r
1175   update_statistics ((long) trie_r, nr, 0);\r
1176   update_statistics ((long) trie_hash, nh, 0);\r
1177   update_statistics ((long) trie_taken, nt, 0);\r
1178 \r
1179   if (trace_flag)\r
1180     probe_show();\r
1181 \r
1182   return 0; // success\r
1183 }\r
1184 #endif\r
1185 \r
1186 #ifdef ALLOCATESAVESTACK\r
1187 int current_save_size = 0;\r
1188 \r
1189 memory_word * realloc_save_stack (int size)\r
1190 {\r
1191   int k, min_size;\r
1192   int n = 0, new_size = 0;\r
1193   memory_word * new_save_stack = NULL;\r
1194 \r
1195   if (trace_flag)\r
1196     printf("Old Address %s == %p\n", "save stack", save_stack);\r
1197 \r
1198   if (current_save_size == save_size)\r
1199   {\r
1200     return save_stack; /* let TeX handle the error */\r
1201   }\r
1202 \r
1203   min_size =  current_save_size / 100 * percent_grow;\r
1204 \r
1205   if (size < min_size)\r
1206     size = min_size;\r
1207 \r
1208   if (size < initial_save_size)\r
1209     size = initial_save_size;\r
1210 \r
1211   for (k = 0; k < MAXSPLITS; k++)\r
1212   {\r
1213     new_size = current_save_size + size;\r
1214 \r
1215     if (new_size > save_size)\r
1216       new_size = save_size;\r
1217 \r
1218     n = (new_size + 1) * sizeof (memory_word);\r
1219 \r
1220     if (trace_flag)\r
1221       trace_memory("save_stack", n);\r
1222 \r
1223     new_save_stack = (memory_word *) REALLOC (save_stack, n);\r
1224 \r
1225     if (new_save_stack != NULL)\r
1226       break;    /* did we get it ? */\r
1227 \r
1228     if (current_save_size == 0)\r
1229       break;  /* initial allocation must work */\r
1230 \r
1231     size = size / 2;          /* else can retry smaller */\r
1232   }\r
1233 \r
1234   if (new_save_stack == NULL)\r
1235   {\r
1236     memory_error("save_stack", n);\r
1237     return save_stack;           /* try and continue !!! */\r
1238   }\r
1239 \r
1240   save_stack = new_save_stack;\r
1241   update_statistics ((long) save_stack, n, current_save_size);\r
1242   current_save_size = new_size;\r
1243 \r
1244   if (trace_flag)\r
1245   {\r
1246     printf("Current %s %d\n", "save_size", current_save_size);\r
1247     printf("New Address %s == %p\n", "save stack", save_stack);\r
1248   }\r
1249 \r
1250   if (trace_flag)\r
1251     probe_show();\r
1252 \r
1253   return save_stack;\r
1254 }\r
1255 #endif\r
1256 \r
1257 #ifdef ALLOCATEINPUTSTACK\r
1258 int current_stack_size = 0;       /* input stack size */\r
1259 \r
1260 in_state_record * realloc_input_stack (int size)\r
1261 {\r
1262   int k, min_size;\r
1263   int n = 0, new_size = 0;\r
1264   in_state_record * new_input_stack = NULL;\r
1265 \r
1266   if (trace_flag)\r
1267     printf("Old Address %s == %p\n", "input stack", input_stack);\r
1268 \r
1269   if (current_stack_size == stack_size)\r
1270   {\r
1271     return input_stack;\r
1272   }\r
1273 \r
1274   min_size =  current_stack_size / 100 * percent_grow;\r
1275 \r
1276   if (size < min_size)\r
1277     size = min_size;\r
1278 \r
1279   if (size < initial_stack_size)\r
1280     size = initial_stack_size;\r
1281 \r
1282   for (k = 0; k < MAXSPLITS; k++)\r
1283   {\r
1284     new_size = current_stack_size + size;\r
1285 \r
1286     if (new_size > stack_size)\r
1287       new_size = stack_size;\r
1288 \r
1289     n = (new_size + 1) * sizeof(in_state_record);\r
1290 \r
1291     if (trace_flag)\r
1292       trace_memory("input_stack", n);\r
1293 \r
1294     new_input_stack = (in_state_record *) REALLOC (input_stack, n);\r
1295 \r
1296     if (new_input_stack != NULL)\r
1297       break;   /* did we get it ? */\r
1298 \r
1299     if (current_stack_size == 0)\r
1300       break; /* initial allocation must work */\r
1301 \r
1302     size = size / 2;          /* else can retry smaller */\r
1303   }\r
1304 \r
1305   if (new_input_stack == NULL)\r
1306   {\r
1307     memory_error("input stack", n);\r
1308     return input_stack;            /* try and continue !!! */\r
1309   }\r
1310 \r
1311   input_stack = new_input_stack;\r
1312   update_statistics ((long) input_stack, n, current_stack_size);\r
1313   current_stack_size = new_size;\r
1314 \r
1315   if (trace_flag)\r
1316   {\r
1317     printf("Current %s %d\n", "stack_size", current_stack_size);\r
1318     printf("New Address %s == %p\n", "input stack", input_stack);\r
1319   }\r
1320 \r
1321   if (trace_flag)\r
1322     probe_show();\r
1323 \r
1324   return input_stack;\r
1325 }\r
1326 #endif\r
1327 \r
1328 #ifdef ALLOCATENESTSTACK\r
1329 int current_nest_size = 0;        /* current nest size */\r
1330 \r
1331 list_state_record * realloc_nest_stack (int size)\r
1332 {\r
1333   int k, min_size;\r
1334   int n = 0, new_size = 0;\r
1335   list_state_record * new_nest = NULL;\r
1336 \r
1337   if (trace_flag)\r
1338     printf("Old Address %s == %p\n", "nest stack", nest);\r
1339 \r
1340   if (current_nest_size == nest_size)\r
1341   {\r
1342     return nest;\r
1343   }\r
1344 \r
1345   min_size =  current_nest_size / 100 * percent_grow;\r
1346 \r
1347   if (size < min_size)\r
1348     size = min_size;\r
1349 \r
1350   if (size < initial_nest_size)\r
1351     size = initial_nest_size;\r
1352 \r
1353   for (k = 0; k < MAXSPLITS; k++)\r
1354   {\r
1355     new_size = current_nest_size + size;\r
1356 \r
1357     if (new_size > nest_size)\r
1358       new_size = nest_size;\r
1359 \r
1360     n = (new_size + 1) * sizeof (list_state_record);\r
1361 \r
1362     if (trace_flag)\r
1363       trace_memory("nest stack", n);\r
1364 \r
1365     new_nest = (list_state_record *) REALLOC (nest, n);\r
1366 \r
1367     if (new_nest != NULL)\r
1368       break;   /* did we get it ? */\r
1369 \r
1370     if (current_nest_size == 0)\r
1371       break;  /* initial allocation must work */\r
1372 \r
1373     size = size / 2;          /* else can retry smaller */\r
1374   }\r
1375 \r
1376   if (new_nest == NULL)\r
1377   {\r
1378     memory_error("nest stack", n);\r
1379     return nest;            /* try and continue !!! */\r
1380   }\r
1381 \r
1382   nest = new_nest;\r
1383   update_statistics ((long) nest, n, current_nest_size);\r
1384   current_nest_size = new_size;\r
1385 \r
1386   if (trace_flag)\r
1387   {\r
1388     printf("Current %s %d\n", "nest_size", current_nest_size);\r
1389     printf("New Address %s == %p\n", "nest stack", nest);\r
1390   }\r
1391 \r
1392   if (trace_flag)\r
1393     probe_show();\r
1394 \r
1395   return nest;\r
1396 }\r
1397 #endif\r
1398 \r
1399 #ifdef ALLOCATEPARAMSTACK\r
1400 int current_param_size = 0;\r
1401 \r
1402 halfword *realloc_param_stack (int size)\r
1403 {\r
1404   int k, min_size;\r
1405   int n = 0, new_size = 0;\r
1406   halfword * new_param = NULL;\r
1407 \r
1408   if (trace_flag)\r
1409     printf("Old Address %s == %p\n", "param stack", param_stack);\r
1410 \r
1411   if (current_param_size == param_size)\r
1412   {\r
1413     return param_stack;\r
1414   }\r
1415 \r
1416   min_size =  current_param_size / 100 * percent_grow;\r
1417 \r
1418   if (size < min_size)\r
1419     size = min_size;\r
1420 \r
1421   if (size < initial_param_size)\r
1422     size = initial_param_size;\r
1423 \r
1424   for (k = 0; k < MAXSPLITS; k++)\r
1425   {\r
1426     new_size = current_param_size + size;\r
1427 \r
1428     if (new_size > param_size)\r
1429       new_size = param_size;\r
1430 \r
1431     n = (new_size + 1) * sizeof(pointer);\r
1432 \r
1433     if (trace_flag)\r
1434       trace_memory("param stack", n);\r
1435 \r
1436     new_param = (pointer *) REALLOC (param_stack, n);\r
1437 \r
1438     if (new_param != NULL)\r
1439       break;    /* did we get it ? */\r
1440 \r
1441     if (current_param_size == 0)\r
1442       break; /* initial allocation must work */\r
1443 \r
1444     size = size / 2; /* else can retry smaller */\r
1445   }\r
1446 \r
1447   if (new_param == NULL)\r
1448   {\r
1449     memory_error("param stack", n);\r
1450     return param_stack;            /* try and continue !!! */\r
1451   }\r
1452 \r
1453   param_stack = new_param;\r
1454   update_statistics((long) param_stack, n, current_param_size);\r
1455   current_param_size = new_size;\r
1456 \r
1457   if (trace_flag)\r
1458   {\r
1459     printf("Current %s %d\n", "param_size", current_param_size);\r
1460     printf("New Address %s == %p\n", "param stack", param_stack);\r
1461   }\r
1462 \r
1463   if (trace_flag)\r
1464     probe_show();\r
1465 \r
1466   return param_stack;\r
1467 }\r
1468 #endif\r
1469 \r
1470 #ifdef ALLOCATEBUFFER\r
1471 int current_buf_size = 0;\r
1472 \r
1473 ASCII_code * realloc_buffer (int size)\r
1474 {\r
1475   int k, min_size;\r
1476   int n = 0, new_size = 0;\r
1477   ASCII_code * new_buffer = NULL;\r
1478 \r
1479   if (trace_flag)\r
1480     printf("Old Address %s == %p\n", "buffer", buffer);\r
1481 \r
1482   if (current_buf_size == buf_size)\r
1483   {\r
1484     return buffer;\r
1485   }\r
1486 \r
1487   min_size =  current_buf_size / 100 * percent_grow;\r
1488 \r
1489   if (size < min_size)\r
1490     size = min_size;\r
1491 \r
1492   if (size < initial_buf_size)\r
1493     size = initial_buf_size;\r
1494 \r
1495   for (k = 0; k < MAXSPLITS; k++)\r
1496   {\r
1497     new_size = current_buf_size + size;\r
1498 \r
1499     if (new_size > buf_size)\r
1500       new_size = buf_size;\r
1501 \r
1502     n = (new_size + 1) * sizeof(ASCII_code);\r
1503 \r
1504     if (trace_flag)\r
1505       trace_memory("buffer", n);\r
1506 \r
1507     new_buffer = (ASCII_code *) REALLOC (buffer, n);\r
1508 \r
1509     if (new_buffer != NULL)\r
1510       break;   /* did we get it ? */\r
1511 \r
1512     if (current_buf_size == 0)\r
1513       break;   /* initial allocation must work */\r
1514 \r
1515     size = size / 2;\r
1516   }\r
1517 \r
1518   if (new_buffer == NULL)\r
1519   {\r
1520     memory_error("buffer", n);\r
1521     return buffer;            /* try and continue !!! */\r
1522   }\r
1523 \r
1524   buffer = new_buffer;\r
1525   update_statistics ((long) buffer, n, current_buf_size);\r
1526 \r
1527 #ifdef USEMEMSET\r
1528   memset(buffer + current_buf_size, 0, new_size - current_buf_size);\r
1529 #else\r
1530   for (k = current_buf_size; k < new_size; k++)\r
1531     buffer[k] = 0;\r
1532 #endif\r
1533 \r
1534   current_buf_size = new_size;\r
1535 \r
1536   if (trace_flag)\r
1537   {\r
1538     printf("Current %s %d\n", "buffer", current_buf_size);\r
1539     printf("New Address %s == %p\n", "buffer", buffer);\r
1540   }\r
1541 \r
1542   if (trace_flag)\r
1543     probe_show();\r
1544 \r
1545   return buffer;\r
1546 }\r
1547 #endif\r
1548 \r
1549 /* here is the main memory allocation routine -- calls the above */\r
1550 /* returns -1 if it fails */\r
1551 /* allocate rather than static 93/Nov/26 */\r
1552 int allocate_memory (void)\r
1553 {\r
1554 #ifdef ALLOCATEINPUTSTACK\r
1555   input_stack = NULL;\r
1556   current_stack_size = 0;\r
1557   input_stack = realloc_input_stack(initial_stack_size);\r
1558 #endif\r
1559 \r
1560 #ifdef ALLOCATENESTSTACK\r
1561   nest = NULL;\r
1562   current_nest_size = 0;\r
1563   nest = realloc_nest_stack(initial_nest_size);\r
1564 #endif\r
1565 \r
1566 #ifdef ALLOCATEPARAMSTACK\r
1567   param_stack = NULL;\r
1568   current_param_size = 0;\r
1569   param_stack = realloc_param_stack(initial_param_size);\r
1570 #endif\r
1571 \r
1572 #ifdef ALLOCATESAVESTACK\r
1573   save_stack = NULL;\r
1574   current_save_size = 0;\r
1575   save_stack = realloc_save_stack (initial_save_size);\r
1576 #endif\r
1577 \r
1578 #ifdef IGNORED\r
1579   buffer = NULL;        /* need to do earlier */\r
1580   current_buf_size = 0;\r
1581   buffer = realloc_buffer (initial_buf_size);\r
1582 #endif\r
1583 \r
1584 #ifdef ALLOCATESTRING\r
1585   str_pool = NULL;\r
1586   current_pool_size = 0;\r
1587   str_start = NULL;\r
1588   current_max_strings = 0;\r
1589 \r
1590 /*  maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */\r
1591   if (is_initex)\r
1592   {\r
1593     if (trace_flag)\r
1594       puts("ini TeX pool and string allocation");\r
1595 \r
1596     str_pool = realloc_str_pool(initial_pool_size);\r
1597     str_start = realloc_str_start(initial_max_strings);\r
1598   }\r
1599 #endif\r
1600 \r
1601 /* the following can save a lot of the usual 800k fixed allocation */\r
1602 #ifdef ALLOCATEFONT\r
1603   font_info = NULL;\r
1604   current_font_mem_size = 0;\r
1605 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */\r
1606 /* if ini-TeX we need to do it here - no format file read later */\r
1607   if (is_initex)\r
1608     font_info = realloc_font_info(initial_font_mem_size);\r
1609 #endif\r
1610 \r
1611 #ifdef ALLOCATEMAIN\r
1612   main_memory = NULL;\r
1613   mem = NULL;\r
1614   mem_min = mem_bot;        /* just to avoid complaints in texbody */\r
1615   mem_top = mem_initex;\r
1616   mem_max = mem_top;\r
1617 /* allocate main memory here if this is iniTeX */\r
1618 /* otherwise wait for format undumping in itex.c ... */\r
1619   if (is_initex)\r
1620   {\r
1621     /* avoid this if format specified on command line ??? */\r
1622     mem = allocate_main_memory(mem_initex); /* made variable ! */\r
1623 \r
1624     if (mem == NULL)\r
1625       return -1;\r
1626   }\r
1627 #endif\r
1628 \r
1629 /* now for the hyphenation exception stuff */\r
1630 #ifdef ALLOCATEHYPHEN\r
1631   hyph_word = NULL;\r
1632   hyph_list = NULL;\r
1633 /* this will be overridden later by what is in format file */\r
1634   hyphen_prime = default_hyphen_prime;\r
1635 /* non ini-TeX use assumes format will be read and that specifies size */\r
1636   if (is_initex)\r
1637   {\r
1638     if (new_hyphen_prime)\r
1639       hyphen_prime = new_hyphen_prime;\r
1640 \r
1641     if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */\r
1642       return -1;\r
1643   }\r
1644 #endif\r
1645 \r
1646 /* now for memory for the part of the hyphenation stuff that always needed */\r
1647 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */\r
1648 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */\r
1649 #ifdef ALLOCATETRIES\r
1650   if (is_initex)\r
1651   {\r
1652     if (allocate_tries (trie_size))\r
1653       return -1;\r
1654   }\r
1655 #endif\r
1656 \r
1657 /* now for memory for hyphenation stuff needed only when running iniTeX */\r
1658 #ifdef ALLOCATEINI\r
1659   if (is_initex)\r
1660   {\r
1661     if (allocate_ini(trie_size))\r
1662       return -1;\r
1663   }\r
1664   else\r
1665   {\r
1666     trie_l = NULL;\r
1667     trie_r = NULL;\r
1668     trie_o = NULL;\r
1669     trie_hash = NULL;\r
1670     trie_c = NULL;\r
1671     trie_taken = NULL;\r
1672   }\r
1673 #endif\r
1674 \r
1675   return 0; // success\r
1676 }\r
1677 \r
1678 /* returns non-zero if error - done to test integrity of stack mostly */\r
1679 int free_memory (void)\r
1680 {\r
1681   unsigned int heap_total = 0;\r
1682 \r
1683   if (trace_flag)\r
1684     puts("free_memory ");\r
1685 \r
1686   if (verbose_flag || trace_flag)\r
1687     show_maximums(stdout); \r
1688 \r
1689   if (trace_flag)\r
1690   {\r
1691     printf("Heap total: %u bytes --- max address %u\n", \r
1692         heap_total, max_address);\r
1693     printf("Main Memory: variable node %lld (%lld - %d);\n"\r
1694       "             one word %d (%d - %d)\n",\r
1695       lo_mem_max - mem_min, mem_min, lo_mem_max,\r
1696       mem_end - hi_mem_min, hi_mem_min, mem_end);\r
1697     puts("Freeing memory again");\r
1698   }\r
1699 \r
1700 /* only free memory if safe ... additional check */\r
1701 #ifdef ALLOCATEINI\r
1702   if (is_initex)\r
1703   {\r
1704     if (trie_taken != NULL)\r
1705       free(trie_taken);\r
1706 \r
1707     if (trie_hash != NULL)\r
1708       free(trie_hash);\r
1709 \r
1710     if (trie_r != NULL)\r
1711       free(trie_r);\r
1712 \r
1713     if (trie_c != NULL)\r
1714       free(trie_c);\r
1715 \r
1716     if (trie_o != NULL)\r
1717       free(trie_o);\r
1718 \r
1719     if (trie_l != NULL)\r
1720       free(trie_l);\r
1721 \r
1722     trie_taken = NULL;\r
1723     trie_hash = NULL;\r
1724     trie_l = NULL;\r
1725     trie_r = NULL;\r
1726     trie_c = NULL;\r
1727     trie_o = NULL;\r
1728   }\r
1729 #endif\r
1730 \r
1731 #ifdef ALLOCATETRIES\r
1732   if (trie_trc != NULL)\r
1733     free(trie_trc);\r
1734 \r
1735   if (trie_tro != NULL)\r
1736     free(trie_tro);\r
1737 \r
1738   if (trie_trl != NULL)\r
1739     free(trie_trl);\r
1740 \r
1741   trie_trc = NULL;\r
1742   trie_tro = NULL;\r
1743   trie_trl = NULL;\r
1744 #endif\r
1745 \r
1746 #ifdef ALLOCATEHYPHEN\r
1747   if (hyph_list != NULL)\r
1748     free(hyph_list);\r
1749 \r
1750   if (hyph_word != NULL)\r
1751     free(hyph_word);\r
1752 \r
1753   hyph_list = NULL;\r
1754   hyph_word = NULL;\r
1755 #endif\r
1756 \r
1757 #ifdef ALLOCATEMAIN\r
1758   if (main_memory != NULL)\r
1759     free(main_memory);\r
1760 \r
1761   main_memory = NULL;\r
1762 #endif\r
1763 \r
1764 #ifdef ALLOCATEFONT\r
1765   if (font_info != NULL)\r
1766     free(font_info);\r
1767 \r
1768   font_info = NULL;\r
1769 #endif\r
1770 \r
1771 #ifdef ALLOCATESTRING\r
1772   if (str_start != NULL)\r
1773     free(str_start);\r
1774 \r
1775   if (str_pool != NULL)\r
1776     free(str_pool);\r
1777 \r
1778   str_start = NULL;\r
1779   str_pool = NULL;\r
1780 #endif\r
1781 \r
1782 #ifdef ALLOCATEPARAMSTACK\r
1783   if (param_stack != NULL)\r
1784     free(param_stack);\r
1785 \r
1786   param_stack = NULL;\r
1787 #endif\r
1788 \r
1789 #ifdef ALLOCATENESTSTACK\r
1790   if (nest != NULL)\r
1791     free(nest);\r
1792 \r
1793   nest = NULL;\r
1794 #endif\r
1795 \r
1796 #ifdef ALLOCATEINPUTSTACK\r
1797   if (input_stack != NULL)\r
1798     free(input_stack);\r
1799 \r
1800   input_stack = NULL;\r
1801 #endif\r
1802 \r
1803 #ifdef ALLOCATESAVESTACK\r
1804   if (save_stack != NULL)\r
1805     free(save_stack);\r
1806 \r
1807   save_stack = NULL;\r
1808 #endif\r
1809 \r
1810   if (format_file != NULL)\r
1811     free(format_file);\r
1812 \r
1813   if (source_direct != NULL)\r
1814     free(source_direct);\r
1815 \r
1816   format_file = NULL;\r
1817   source_direct = NULL;\r
1818 \r
1819   if (dvi_file_name != NULL)\r
1820     free(dvi_file_name);\r
1821 \r
1822   if (log_file_name != NULL)\r
1823     free(log_file_name);\r
1824 \r
1825   if (pdf_file_name != NULL)\r
1826     free(pdf_file_name);\r
1827 \r
1828   pdf_file_name = NULL;\r
1829   log_file_name = NULL;\r
1830   dvi_file_name = NULL;\r
1831 \r
1832   return 0;\r
1833 }\r
1834 \r
1835 boolean prime (int x)\r
1836 {\r
1837   int k;\r
1838   int sum = 1;    /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */\r
1839 \r
1840   if (x % 2 == 0)\r
1841     return false;\r
1842 \r
1843   for (k = 3; k < x; k = k + 2)\r
1844   {\r
1845     if (x % k == 0)\r
1846       return false;\r
1847 \r
1848     if (sum * 4 > x)\r
1849       return true;\r
1850 \r
1851     sum += k;\r
1852   }\r
1853 \r
1854   return true;\r
1855 }\r
1856 \r
1857 int quitflag  = 0;\r
1858 boolean show_use = false;\r
1859 \r
1860 void complainarg (int c, char *s)\r
1861 {\r
1862   printf("ERROR: Do not understand `%c' argument value `%s'\n", c, s);\r
1863   show_use = true;\r
1864 }\r
1865 \r
1866 /* following is list of allowed command line flags and args */\r
1867 \r
1868 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";\r
1869 \r
1870 void reorderargs (int ac, char **av)\r
1871 {\r
1872   int n, m;\r
1873   char *s, *t;\r
1874   char takeargs[256];   /* large enough for all command line arg chars */\r
1875 \r
1876   if (ac < 3)\r
1877   {\r
1878     return; /* no args ! */\r
1879   }\r
1880 \r
1881   s = allowedargs;\r
1882   t = takeargs;   /* list of those that take args */\r
1883 \r
1884   while (*s != '\0' && *(s + 1) != '\0')\r
1885   {\r
1886     if (*(s + 1) == '=')\r
1887       *t++ = *s++;   /* copy over --- without the = */\r
1888 \r
1889     s++;\r
1890   }\r
1891 \r
1892   *t = '\0';\r
1893 \r
1894   if (trace_flag)\r
1895   {\r
1896     show_line(takeargs, 0);\r
1897     wterm_cr();\r
1898   }\r
1899   \r
1900   n = 1;\r
1901 \r
1902   for (;;)\r
1903   {\r
1904     if (*av[n] != '-')\r
1905       break;\r
1906 \r
1907     if (n + 1 < ac && *(av[n] + 2) == '\0' &&\r
1908       strchr(takeargs, *(av[n] + 1)) != NULL)\r
1909       n += 2; /* step over it */\r
1910     else\r
1911       n++;\r
1912 \r
1913     if (n == ac)\r
1914       break;\r
1915   }\r
1916 \r
1917   for (;;)\r
1918   {\r
1919     if (n == ac)\r
1920       break;\r
1921 \r
1922     m = n;\r
1923 \r
1924     while (m < ac && *av[m] != '-')\r
1925       m++;  /* first command */\r
1926 \r
1927     if (m == ac)\r
1928       break;\r
1929 /* does it take an argument ? and is this argument next ? */\r
1930 /* check first whether the `-x' is isolated, or arg follows directly */\r
1931 /* then check whether this is one of those that takes an argument */\r
1932     if (m+1 < ac && *(av[m] + 2) == '\0' &&\r
1933       strchr(takeargs, *(av[m] + 1)) != NULL)\r
1934     {\r
1935       s = av[m];      /*  move command down before non-command */\r
1936       t = av[m + 1];\r
1937 \r
1938       for (; m > n; m--)\r
1939         av[m + 1] = av[m - 1];\r
1940 \r
1941       av[n] = s;\r
1942       av[n + 1] = t;\r
1943       n += 2;       /* step over moved args */\r
1944     }\r
1945     else\r
1946     {\r
1947       s = av[m];      /*  move command down before non-command */\r
1948 \r
1949       for (; m > n; m--)\r
1950         av[m] = av[m - 1];\r
1951 \r
1952       av[n] = s;\r
1953       n++;        /* step over moved args */\r
1954     }\r
1955   }\r
1956 }\r
1957 \r
1958 int test_align (long address, int size, const char *str)\r
1959 {\r
1960   int n;\r
1961 \r
1962   if (size > sizeof(void *))\r
1963     n = address % sizeof(void *);\r
1964   else\r
1965     n = address % size;\r
1966 \r
1967   if (n != 0)\r
1968     printf("OFFSET %d (ELEMENT %d) in %s\n", n, size, str);\r
1969 \r
1970   return n;\r
1971 }\r
1972 \r
1973 /* activate detailed checking of alignment when trace_flag is set */\r
1974 \r
1975 void check_fixed_align (int flag)\r
1976 {\r
1977   (void) flag;\r
1978 \r
1979   if (test_align ((long) &mem_top, 4, "FIXED ALIGNMENT"))\r
1980   {\r
1981     puts("PLEASE RECOMPILE ME!");\r
1982   }\r
1983 \r
1984 #ifdef CHECKALIGNMENT\r
1985   if (!flag)\r
1986     return;\r
1987 \r
1988   test_align ((long) &mem_top, 4, "mem_top");\r
1989   test_align ((long) &mem_max, 4, "mem_max");\r
1990   test_align ((long) &mem_min, 4, "mem_min");\r
1991   test_align ((long) &bad, 4, "bad");\r
1992   test_align ((long) &trie_size, 4, "trie_size");\r
1993   test_align ((long) &xord, sizeof(xord[0]), "xord");\r
1994   test_align ((long) &xchr, sizeof(xchr[0]), "xchr");\r
1995   test_align ((long) &name_length, 4, "name_length");\r
1996   test_align ((long) &first, 4, "first");\r
1997   test_align ((long) &last, 4, "last");\r
1998   test_align ((long) &max_buf_stack, 4, "max_buf_stack");\r
1999   test_align ((long) &pool_ptr, 4, "pool_ptr");\r
2000   test_align ((long) &str_ptr, 4, "str_ptr");\r
2001   test_align ((long) &init_pool_ptr, 4, "init_pool_ptr");\r
2002   test_align ((long) &init_str_ptr, 4, "init_str_ptr");\r
2003   test_align ((long) &log_file, 4, "log_file");\r
2004   test_align ((long) &tally, 4, "tally");\r
2005   test_align ((long) &term_offset, 4, "term_offset");\r
2006   test_align ((long) &file_offset, 4, "file_offset");\r
2007   test_align ((long) &trick_count, 4, "trick_count");\r
2008   test_align ((long) &first_count, 4, "first_count");\r
2009   test_align ((long) &deletions_allowed, 4, "deletions_allowed");\r
2010   test_align ((long) &set_box_allowed, 4, "set_box_allowed");\r
2011   test_align ((long) &help_line, sizeof(help_line[0]), "help_line");\r
2012   test_align ((long) &use_err_help, 4, "use_err_help");\r
2013   test_align ((long) &interrupt, 4, "interrupt");\r
2014   test_align ((long) &OK_to_interrupt, 4, "OK_to_interrupt");\r
2015   test_align ((long) &arith_error, 4, "arith_error");\r
2016   test_align ((long) &tex_remainder, 4, "tex_remainder");\r
2017   test_align ((long) &temp_ptr, 4, "temp_ptr");\r
2018   test_align ((long) &lo_mem_max, 4, "lo_mem_max");\r
2019   test_align ((long) &hi_mem_min, 4, "hi_mem_min");\r
2020   test_align ((long) &var_used, 4, "var_used");\r
2021   test_align ((long) &dyn_used, 4, "dyn_used");\r
2022   test_align ((long) &avail, 4, "avail");\r
2023   test_align ((long) &mem_end, 4, "mem_end");\r
2024   test_align ((long) &mem_start, 4, "mem_start");\r
2025   test_align ((long) &rover, 4, "rover");\r
2026   test_align ((long) &font_in_short_display, 4, "font_in_short_display");\r
2027   test_align ((long) &depth_threshold, 4, "depth_threshold");\r
2028   test_align ((long) &breadth_max, 4, "breadth_max");\r
2029   test_align ((long) &nest, sizeof(nest[0]), "nest");\r
2030   // test_align ((long) &xeq_level, sizeof(xeq_level[0]), "xeq_level");\r
2031   test_align ((long) &zzzad, sizeof(zzzad[0]), "zzzad");\r
2032   // test_align ((long) &hash, sizeof(hash[0]), "hash");\r
2033   test_align ((long) &zzzae, sizeof(zzzae[0]), "zzzae");\r
2034   test_align ((long) &save_stack, sizeof(save_stack[0]), "save_stack");\r
2035   test_align ((long) &input_stack, sizeof(input_stack[0]), "input_stack");\r
2036   test_align ((long) &input_file, sizeof(input_file[0]), "input_file");\r
2037   test_align ((long) &line_stack, sizeof(line_stack[0]), "line_stack");\r
2038   test_align ((long) &param_stack, sizeof(param_stack[0]), "param_stack");\r
2039   test_align ((long) &cur_mark, sizeof(cur_mark[0]), "cur_mark");\r
2040   test_align ((long) &pstack, sizeof(pstack[0]), "pstack");\r
2041   test_align ((long) &read_file, sizeof(read_file[0]), "read_file");\r
2042   test_align ((long) &font_check, sizeof(font_check[0]), "font_check");\r
2043   test_align ((long) &font_size, sizeof(font_size[0]), "font_size");\r
2044   test_align ((long) &font_dsize, sizeof(font_dsize[0]), "font_dsize");\r
2045   test_align ((long) &font_params, sizeof(font_params[0]), "font_params");\r
2046   test_align ((long) &font_name, sizeof(font_name[0]), "font_name");\r
2047   test_align ((long) &font_area, sizeof(font_area[0]), "font_area");\r
2048   test_align ((long) &font_bc, sizeof(font_bc[0]), "font_bc");\r
2049   test_align ((long) &font_ec, sizeof(font_ec[0]), "font_ec");\r
2050   test_align ((long) &font_glue, sizeof(font_glue[0]), "font_glue");\r
2051   test_align ((long) &font_used, sizeof(font_used[0]), "font_used");\r
2052   test_align ((long) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");\r
2053   test_align ((long) &skew_char, sizeof(skew_char[0]), "skew_char");\r
2054   test_align ((long) &bchar_label, sizeof(bchar_label[0]), "bchar_label");\r
2055   test_align ((long) &font_bchar, sizeof(font_bchar[0]), "font_bchar");\r
2056   test_align ((long) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");\r
2057   test_align ((long) &char_base, sizeof(char_base[0]), "char_base");\r
2058   test_align ((long) &width_base, sizeof(width_base[0]), "width_base");\r
2059   test_align ((long) &height_base, sizeof(height_base[0]), "height_base");\r
2060   test_align ((long) &depth_base, sizeof(depth_base[0]), "depth_base");\r
2061   test_align ((long) &italic_base, sizeof(italic_base[0]), "italic_base");\r
2062   test_align ((long) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");\r
2063   test_align ((long) &kern_base, sizeof(kern_base[0]), "kern_base");\r
2064   test_align ((long) &exten_base, sizeof(exten_base[0]), "exten_base");\r
2065   test_align ((long) &param_base, sizeof(param_base[0]), "param_base");\r
2066   test_align ((long) &total_stretch, sizeof(total_stretch[0]), "total_stretch");\r
2067   test_align ((long) &total_shrink, sizeof(total_shrink[0]), "total_shrink");\r
2068   test_align ((long) &active_width, sizeof(active_width[0]), "active_width");\r
2069   test_align ((long) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");\r
2070   test_align ((long) &background, sizeof(background[0]), "background");\r
2071   test_align ((long) &break_width, sizeof(break_width[0]), "break_width");\r
2072   test_align ((long) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");\r
2073   test_align ((long) &best_place, sizeof(best_place[0]), "best_place");\r
2074   test_align ((long) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");\r
2075   test_align ((long) &hc, sizeof(hc[0]), "hc");\r
2076   test_align ((long) &hu, sizeof(hu[0]), "hu");\r
2077   test_align ((long) &hyf, sizeof(hyf[0]), "hyf");\r
2078   // test_align ((long) &x, sizeof(x[0]), "x");\r
2079   test_align ((long) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");\r
2080   test_align ((long) &hyf_num, sizeof(hyf_num[0]), "hyf_num");\r
2081   test_align ((long) &hyf_next, sizeof(hyf_next[0]), "hyf_next");\r
2082   test_align ((long) &op_start, sizeof(op_start[0]), "op_start");\r
2083   // test_align ((long) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash");\r
2084   test_align ((long) &trie_used, sizeof(trie_used[0]), "trie_used");\r
2085 /*  test_align ((long) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/\r
2086   test_align ((long) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");\r
2087   test_align ((long) &trie_min, sizeof(trie_min[0]), "trie_min");\r
2088   test_align ((long) &page_so_far, sizeof(page_so_far[0]), "page_so_far");\r
2089   test_align ((long) &write_file, sizeof(write_file[0]), "write_file");\r
2090   test_align ((long) &write_open, sizeof(write_open[0]), "write_open");\r
2091 #endif\r
2092 }\r
2093 \r
2094 void check_alloc_align (int flag)\r
2095 {\r
2096   (void) flag;\r
2097 \r
2098   if (test_align((long) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))\r
2099     puts("PLEASE RECOMPILE ME!");\r
2100 \r
2101 #ifdef CHECKALIGNMENT\r
2102   if (!flag)\r
2103     return;\r
2104 \r
2105 #ifndef ALLOCZEQTB\r
2106   test_align ((long) eqtb, sizeof(eqtb[0]), "eqtb"); \r
2107 #endif\r
2108 \r
2109   test_align ((long) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */\r
2110   test_align ((long) str_start, sizeof(str_start[0]), "str_start");\r
2111   test_align ((long) mem, sizeof(mem[0]), "main memory");\r
2112   test_align ((long) font_info, sizeof(font_info[0]), "font memory");\r
2113   test_align ((long) trie_trl, sizeof(trie_trl[0]), "trie_trl");\r
2114   test_align ((long) trie_tro, sizeof(trie_tro[0]), "trie_tro");\r
2115   test_align ((long) trie_trc, sizeof(trie_trc[0]), "trie_trc");\r
2116   test_align ((long) hyph_word, sizeof(hyph_word[0]), "hyph_word");\r
2117   test_align ((long) hyph_list, sizeof(hyph_list[0]), "hyph_list");\r
2118 /*  test_align ((long) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */\r
2119   test_align ((long) trie_o, sizeof(trie_o[0]), "trie_o");\r
2120   test_align ((long) trie_l, sizeof(trie_l[0]), "trie_l");\r
2121   test_align ((long) trie_r, sizeof(trie_r[0]), "trie_r");\r
2122   test_align ((long) trie_hash, sizeof(trie_hash[0]), "trie_hash");\r
2123   test_align ((long) trie_taken, sizeof(trie_taken[0]), "trie_taken");\r
2124 #endif\r
2125 }\r
2126 \r
2127 boolean shorten_file_name  = false; /* don't shorten file names to 8+3 for DOS */\r
2128 \r
2129 /* cache to prevent allocating twice in a row */\r
2130 \r
2131 char * lastname  = NULL;\r
2132 char * lastvalue = NULL;\r
2133 \r
2134 /* returns allocated string -- these strings are not freed again */\r
2135 /* is it safe to do that now ? 98/Jan/31 */\r
2136 char * grabenv (const char * varname)\r
2137 {\r
2138   char * s;\r
2139 \r
2140   if (varname == NULL)\r
2141     return NULL;\r
2142 \r
2143   if (*varname == '\0')\r
2144     return NULL;\r
2145 \r
2146   if (lastname != NULL && strcasecmp(lastname, varname) == 0)\r
2147   {\r
2148     if (trace_flag)\r
2149       printf("Cache hit: %s=%s\n", lastname, lastvalue);\r
2150 \r
2151     return xstrdup(lastvalue);\r
2152   }\r
2153 \r
2154   s = getenv(varname);\r
2155 \r
2156   if (s != NULL)\r
2157   {\r
2158     if (lastname != NULL)\r
2159       free(lastname);\r
2160 \r
2161     lastname = xstrdup(varname);\r
2162 \r
2163     if (lastvalue != NULL)\r
2164       free(lastvalue);\r
2165 \r
2166     lastvalue = xstrdup(s);\r
2167 \r
2168     return xstrdup(s);\r
2169   }\r
2170   else\r
2171     return NULL;\r
2172 }\r
2173 \r
2174 void flush_trailing_slash (char * directory)\r
2175 {\r
2176   char * s;\r
2177 \r
2178   if (strcmp(directory, "") != 0)\r
2179   {\r
2180     s = directory + strlen(directory) - 1;\r
2181 \r
2182     if (*s == '\\' || *s == '/')\r
2183       *s = '\0';\r
2184   }\r
2185 }\r
2186 \r
2187 void knuthify (void)\r
2188 {\r
2189   restrict_to_ascii     = false; /* don't complain non ASCII */\r
2190   allow_patterns        = false; /* don't allow pattern redefinition */\r
2191   show_in_hex           = true;  /* show character code in hex */\r
2192   show_in_dos           = false; /* redundant with previous */\r
2193   show_numeric          = false; /* don't show character code decimal */\r
2194   show_missing          = false; /* don't show missing characters */\r
2195   civilize_flag         = false; /* don't reorder date fields */\r
2196   c_style_flag          = false; /* don't add file name to error msg */\r
2197   show_fmt_flag         = false; /* don't show format file in log */\r
2198   show_tfm_flag         = false; /* don't show metric file in log */\r
2199   tab_step              = 0;\r
2200   show_line_break_stats = false; /* do not show line break stats */\r
2201   show_fonts_used       = false;\r
2202   default_rule          = 26214; /* revert to default rule thickness */\r
2203   pseudo_tilde          = false;\r
2204   pseudo_space          = false;\r
2205   truncate_long_lines   = false;\r
2206   allow_quoted_names    = false;\r
2207   show_cs_names         = false;\r
2208   ignore_frozen         = false;\r
2209   suppress_f_ligs       = false;\r
2210   full_file_name_flag   = false;\r
2211   knuth_flag            = true;  /* so other code can know about this */\r
2212 }\r
2213 \r
2214 /* following made global so analyze_flag can be made separate procedure */\r
2215 \r
2216 char * xchr_file = NULL;\r
2217 char * repl_file = NULL;\r
2218 \r
2219 const char * short_options = "m:e:h:0:H:g:P:o:l:a:r:kwvpiKLZMd2t?u";\r
2220 \r
2221 static struct option long_options[] =\r
2222 {\r
2223   {"main-memory",   required_argument, NULL, 'm'},\r
2224   {"hyph-size",     required_argument, NULL, 'e'},\r
2225   {"trie-size",     required_argument, NULL, 'h'},\r
2226   {"backend",       required_argument, NULL, '0'},\r
2227   {"tab-step",      required_argument, NULL, 'H'},\r
2228   {"percent-grow",  required_argument, NULL, 'g'},\r
2229   {"default-rule",  required_argument, NULL, 'P'},\r
2230   {"dvi-dir",       required_argument, NULL, 'o'},\r
2231   {"log-dir",       required_argument, NULL, 'l'},\r
2232   {"aux-dir",       required_argument, NULL, 'a'},\r
2233   {"key-file",      required_argument, NULL, 'k'},\r
2234   {"jobname",       required_argument, NULL, 'r'},\r
2235   {"showhex",       no_argument,       NULL, 'w'},\r
2236   {"verbose",       no_argument,       NULL, 'v'},\r
2237   {"patterns",      no_argument,       NULL, 'p'},\r
2238   {"initex",        no_argument,       NULL, 'i'},\r
2239   {"knuthify",      no_argument,       NULL, 'K'},\r
2240   {"cstyle",        no_argument,       NULL, 'L'},\r
2241   {"showtfm",       no_argument,       NULL, 'Z'},\r
2242   {"showmissing",   no_argument,       NULL, 'M'},\r
2243   {"deslash",       no_argument,       NULL, 'd'},\r
2244   {"suppressflig",  no_argument,       NULL, '2'},\r
2245   {"trace",         no_argument,       NULL, 't'},\r
2246   {"help",          no_argument,       NULL, '?'},\r
2247   {"usage",         no_argument,       NULL, 'u'},\r
2248   {NULL,            0, 0, 0}\r
2249 };\r
2250 \r
2251 int analyze_flag (int c, char * optarg)\r
2252 {\r
2253   switch (c)\r
2254   {\r
2255     case 'r':\r
2256       c_job_name = optarg;\r
2257       break;\r
2258     case 'v':\r
2259       verbose_flag = true;\r
2260       break;\r
2261     case 'i':\r
2262       is_initex = true;\r
2263       break;\r
2264     case 'Q':\r
2265       interaction = batch_mode;\r
2266       break;\r
2267     case 'R':\r
2268       interaction = nonstop_mode;\r
2269       break;\r
2270     case 'S':\r
2271       interaction = scroll_mode;\r
2272       break;\r
2273     case 'T':\r
2274       interaction = error_stop_mode;\r
2275       break;\r
2276     case 'K':\r
2277       knuthify();\r
2278       break;\r
2279     case 'L':\r
2280       c_style_flag = true;\r
2281       break;\r
2282     case 'Z':\r
2283       show_tfm_flag = true;\r
2284       break;\r
2285     case 'M':\r
2286       show_missing = false;\r
2287       break;\r
2288     case 'd':\r
2289       deslash = false;\r
2290       break;\r
2291     case 'p':\r
2292       allow_patterns = true;\r
2293       break;\r
2294     case 'w':\r
2295       show_in_hex = true;\r
2296       break;\r
2297     case 'j':\r
2298       show_in_dos = true;\r
2299       break;\r
2300     case 'n':\r
2301       restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */\r
2302       break;\r
2303     case 'f':\r
2304       show_fonts_used = false;\r
2305       break;\r
2306     case '8':\r
2307       shorten_file_name = true;\r
2308       break;\r
2309     case '9':\r
2310       show_cs_names = true;\r
2311       break;\r
2312     case '4':\r
2313       ignore_frozen = true;\r
2314       break;\r
2315     case 'J':\r
2316       show_line_break_stats = false; /* 96/Feb/8 */\r
2317       break;\r
2318     case 'O':\r
2319       show_fmt_flag = false; /* 94/Jun/21 */\r
2320       break;\r
2321     case '2':\r
2322       suppress_f_ligs = true; /* 99/Jan/5 f-lig */\r
2323       break;\r
2324     case 'z':\r
2325       full_file_name_flag = false; // 00 Jun 18\r
2326       break;\r
2327     case 't':\r
2328       trace_flag = true;\r
2329       break;\r
2330     case 'q':\r
2331       quitflag++; /* 93/Dec/16 */\r
2332       break;\r
2333 /* The following are really obscure and should not be advertized */\r
2334     case 's':\r
2335       show_current = false;\r
2336       break;\r
2337     case 'N':\r
2338       show_numeric = false;\r
2339       break;\r
2340     case 'A':\r
2341       civilize_flag = false;\r
2342       break; \r
2343     case 'B':\r
2344       open_trace_flag = true;\r
2345       break;\r
2346     case 'Y':\r
2347       reorder_arg_flag = false; /* local */\r
2348       break;\r
2349 \r
2350     case 'm':\r
2351       if (optarg == 0)\r
2352         mem_initex = mem_top;\r
2353       else\r
2354         mem_initex = atoi(optarg) * 1024;\r
2355 \r
2356       if (mem_initex == 0)\r
2357         complainarg(c, optarg);\r
2358 \r
2359       mem_spec_flag = true;\r
2360       break;\r
2361 \r
2362 #ifdef VARIABLETRIESIZE\r
2363     case 'h':\r
2364       if (optarg == 0)\r
2365       {\r
2366         //trie_size = atoi(kpse_var_value("trie_size"));\r
2367         trie_size = default_trie_size;\r
2368       }\r
2369       else\r
2370         trie_size = atoi(optarg);\r
2371 \r
2372       if (trie_size == 0)\r
2373         complainarg(c, optarg);\r
2374       break;\r
2375 #endif\r
2376 \r
2377 #ifdef ALLOCATEHYPHEN\r
2378     case 'e':\r
2379       if (optarg == 0)\r
2380         new_hyphen_prime = hyphen_prime * 2;\r
2381       else\r
2382         new_hyphen_prime = atoi(optarg);\r
2383 \r
2384       if (new_hyphen_prime == 0)\r
2385         complainarg(c, optarg);\r
2386 \r
2387       break;\r
2388 #endif\r
2389     case 'g':\r
2390       if (optarg == 0)\r
2391         percent_grow = 62;\r
2392       else\r
2393         percent_grow = atoi(optarg);\r
2394 \r
2395       if (percent_grow == 0)\r
2396         complainarg(c, optarg);\r
2397 \r
2398       break;\r
2399 \r
2400     case 'U':\r
2401       if (optarg == 0)\r
2402         pseudo_tilde = 0;\r
2403       else\r
2404         pseudo_tilde = atoi(optarg);\r
2405 \r
2406       if (pseudo_tilde > 255)\r
2407         pseudo_tilde = 255;\r
2408       else if (pseudo_tilde < 128)\r
2409         pseudo_tilde = 128;\r
2410 \r
2411       break;\r
2412 \r
2413     case 'H':\r
2414       if (optarg == 0)\r
2415         tab_step = 8;\r
2416       else\r
2417         tab_step = atoi(optarg);\r
2418       if (tab_step == 0)\r
2419         complainarg(c, optarg);\r
2420       break;\r
2421 \r
2422     case 'x':\r
2423       if (optarg == 0)\r
2424         xchr_file = xstrdup("xchr.map");\r
2425       else\r
2426         xchr_file = xstrdup(optarg);\r
2427 \r
2428       if (xchr_file == NULL || *xchr_file == '\0')\r
2429         complainarg(c, optarg);\r
2430       break;\r
2431 \r
2432     case 'k':\r
2433       if (optarg == 0)\r
2434         repl_file = xstrdup("repl.key");\r
2435       else\r
2436         repl_file = xstrdup(optarg);\r
2437 \r
2438       if (repl_file == NULL || *repl_file == '\0')\r
2439         complainarg(c, optarg);\r
2440       break;\r
2441 \r
2442     case 'P':\r
2443       if (optarg == 0)\r
2444         default_rule = 26214;\r
2445       else\r
2446         default_rule = atoi(optarg);\r
2447 \r
2448       if (default_rule == 0)\r
2449         complainarg(c, optarg);\r
2450       break;\r
2451 \r
2452     case 'E':\r
2453       if (optarg != 0)\r
2454         putenv(optarg);\r
2455       else\r
2456         complainarg(c, optarg);\r
2457       break;\r
2458 \r
2459     case 'o':\r
2460       if (optarg == 0)\r
2461         dvi_directory = "";\r
2462       else\r
2463         dvi_directory = xstrdup(optarg);\r
2464 \r
2465       if (strcmp(dvi_directory, "") == 0)\r
2466         complainarg(c, optarg);\r
2467 \r
2468       break;\r
2469 \r
2470     case 'l':\r
2471       if (optarg == 0)\r
2472         log_directory = "";\r
2473       else\r
2474         log_directory = xstrdup(optarg);\r
2475 \r
2476       if (strcmp(log_directory, "") == 0)\r
2477         complainarg(c, optarg);\r
2478 \r
2479       break;\r
2480 \r
2481     case 'a':\r
2482       if (optarg == 0)\r
2483         aux_directory = "";\r
2484       else\r
2485         aux_directory = xstrdup(optarg);\r
2486 \r
2487       if (strcmp(aux_directory, "") == 0)\r
2488         complainarg(c, optarg);\r
2489 \r
2490       break;\r
2491 \r
2492     case '?':\r
2493     default:\r
2494       show_use = true;\r
2495       return -1;\r
2496       break;\r
2497   }\r
2498 \r
2499   return 0;\r
2500 }\r
2501 \r
2502 void strip_name (char *pathname)\r
2503 {\r
2504   char *s;\r
2505 \r
2506   if ((s = strrchr(pathname, '\\')) != NULL)\r
2507     ;\r
2508   else if ((s = strrchr(pathname, '/')) != NULL)\r
2509     ;\r
2510   else if ((s = strrchr(pathname, ':')) != NULL)\r
2511     s++;\r
2512   else\r
2513     s = pathname;\r
2514 \r
2515   *s = '\0';\r
2516 }\r
2517 \r
2518 int read_command_line (int ac, char **av)\r
2519\r
2520   int c;\r
2521   char *optargnew;\r
2522   int option_idx = 0;\r
2523 \r
2524   if (ac < 2)\r
2525     return 0;\r
2526 \r
2527   while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)\r
2528   {\r
2529     if (optarg != 0 && *optarg == '=')\r
2530       optargnew = optarg + 1;\r
2531     else\r
2532       optargnew = optarg;\r
2533 \r
2534     analyze_flag(c, optargnew);\r
2535   }\r
2536 \r
2537   if (show_use || quitflag == 3)\r
2538   {\r
2539     stamp_it(log_line);\r
2540     strcat(log_line, "\n");\r
2541     show_line(log_line, 0);\r
2542 \r
2543     if (show_use)\r
2544       show_usage();\r
2545     else if (quitflag == 3)\r
2546     {\r
2547       strcat(log_line, "\n");\r
2548       show_line(log_line, 0);\r
2549     }\r
2550 \r
2551     return -1; // failure\r
2552   } \r
2553 \r
2554   if (repl_file != NULL && *repl_file != '\0')\r
2555   {\r
2556     if (read_xchr_file(repl_file, 1, av))\r
2557     {\r
2558       if (trace_flag)\r
2559         puts("KEY REPLACE ON");\r
2560 \r
2561       key_replace = true;\r
2562     }\r
2563   } \r
2564 \r
2565   if (xchr_file != NULL && *xchr_file != '\0')\r
2566   {\r
2567     if (read_xchr_file(xchr_file, 0, av))\r
2568     {\r
2569       if (trace_flag)\r
2570         puts("NON ASCII ON");\r
2571 \r
2572       non_ascii = true;\r
2573     }\r
2574   } \r
2575 \r
2576   return 0;\r
2577 }\r
2578 \r
2579 int init_commands (int ac, char **av)\r
2580 {\r
2581   shipout_flag          = out_dvi_flag;\r
2582   is_initex             = false; \r
2583   allow_patterns        = false;\r
2584   reset_exceptions      = false;\r
2585   non_ascii             = false;\r
2586   key_replace           = false;\r
2587   open_trace_flag       = false;\r
2588   trace_flag            = false;\r
2589   verbose_flag          = false;\r
2590   restrict_to_ascii     = false;\r
2591   show_in_hex           = false; /* default is not to show as hex code ^^ 00/Jun/18 */\r
2592   show_in_dos           = false; /* default is not to translate to DOS 850 */ \r
2593   return_flag           = true;  // hard wired now\r
2594   trimeof               = true;  // hard wired now\r
2595   deslash               = true;\r
2596   pseudo_tilde          = 254;   /* default '~' replace 95/Sep/26 filledbox DOS 850 */\r
2597   pseudo_space          = 255;   /* default ' ' replace 97/June/5 nbspace DOS 850 */\r
2598   default_rule          = 26214;\r
2599   show_current          = true;\r
2600   civilize_flag         = true;\r
2601   show_numeric          = true;\r
2602   show_missing          = true;\r
2603   c_style_flag          = false;\r
2604   show_fmt_flag         = true;\r
2605   show_tfm_flag         = false; /* don't show metric file in log */\r
2606   shorten_file_name     = false; /* don't shorten file names to 8+3 */\r
2607   truncate_long_lines   = true;  /* truncate long lines */\r
2608   tab_step              = 0;     /* do not replace tabs with spaces */\r
2609   show_line_break_stats = true;  /* show line break statistics 96/Feb/8 */\r
2610   show_fonts_used       = true;  /* show fonts used in LOG file 97/Dec/24 */\r
2611   allow_quoted_names    = true;  /* allow quoted names with spaces 98/Mar/15 */\r
2612   show_cs_names         = false;\r
2613   knuth_flag            = false;\r
2614   full_file_name_flag   = true;  /* new default 2000 June 18 */\r
2615   errout                = stdout; /* as opposed to stderr say --- used ??? */\r
2616   new_hyphen_prime      = 0;\r
2617 \r
2618 #ifdef VARIABLETRIESIZE\r
2619   // trie_size = default_trie_size;\r
2620   trie_size = 0;\r
2621 #endif\r
2622 \r
2623   mem_extra_high = 0;\r
2624   mem_extra_low  = 0;\r
2625   mem_initex     = 0;\r
2626   format_name    = "plain";\r
2627 \r
2628   if (read_command_line(ac, av) < 0)\r
2629     return -1;\r
2630 \r
2631   if (optind == 0)\r
2632     optind = ac;\r
2633 \r
2634   return 0;\r
2635 }\r
2636 \r
2637 void initial_memory (void)\r
2638 {\r
2639   /* set initial memory allocations */\r
2640   if (mem_extra_high < 0)\r
2641     mem_extra_high = 0;\r
2642 \r
2643   if (mem_extra_low < 0)\r
2644     mem_extra_low = 0;\r
2645 \r
2646   if (mem_initex < 0)\r
2647     mem_initex = 0;\r
2648 \r
2649   if (is_initex)\r
2650   {\r
2651  #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)\r
2652     if (mem_extra_high != 0 || mem_extra_low != 0)\r
2653     {\r
2654       puts("ERROR: Cannot extend main memory in initex");\r
2655       mem_extra_high = 0;\r
2656       mem_extra_low = 0;\r
2657     }\r
2658 #endif\r
2659   }\r
2660   else\r
2661   {\r
2662     if (mem_initex != 0)\r
2663     {\r
2664       puts("ERROR: Can only set initial main memory size in initex");\r
2665       mem_initex = 0;\r
2666     }\r
2667 \r
2668     if (trie_size != 0)\r
2669     {\r
2670       puts("ERROR: Need only set hyphenation trie size in initex");\r
2671 /* trie_size = 0; */\r
2672     }\r
2673   }\r
2674   if (mem_initex == 0)\r
2675     mem_initex = default_mem_top;\r
2676 \r
2677   if (trie_size == 0)\r
2678     trie_size = default_trie_size;\r
2679 \r
2680 /* Just in case user mistakenly specified words instead of kilo words */\r
2681   if (mem_extra_high > 10000L * 1024L)\r
2682     mem_extra_high = mem_extra_high / 1024;\r
2683 \r
2684   if (mem_extra_low > 10000L * 1024L)\r
2685     mem_extra_low = mem_extra_low / 1024;\r
2686 \r
2687   if (mem_initex > 10000L * 1024L)\r
2688     mem_initex = mem_initex / 1024;\r
2689 \r
2690   if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */\r
2691   {\r
2692     puts("WARNING: There may be no benefit to asking for so much memory");\r
2693 /* mem_initex = 2048 * 1024; */\r
2694   }\r
2695 \r
2696   if (new_hyphen_prime < 0)\r
2697     new_hyphen_prime = 0;\r
2698 \r
2699   if (new_hyphen_prime > 0)\r
2700   {\r
2701     if (! is_initex)\r
2702       puts("ERROR: Can only set hyphen prime in initex");\r
2703     else\r
2704     {\r
2705       if (new_hyphen_prime % 2 == 0)\r
2706         new_hyphen_prime++;\r
2707 \r
2708       while (!prime(new_hyphen_prime))\r
2709         new_hyphen_prime = new_hyphen_prime + 2;\r
2710 \r
2711       if (trace_flag)\r
2712         printf("Using %d as hyphen prime\n", new_hyphen_prime);\r
2713     }\r
2714   }\r
2715 \r
2716   if (percent_grow > 100)\r
2717     percent_grow = percent_grow - 100;\r
2718 \r
2719   if (percent_grow > 100)\r
2720     percent_grow = 100;   /* upper limit - double */\r
2721 \r
2722   if (percent_grow < 10)\r
2723     percent_grow = 10;   /* lower limit - 10% */\r
2724 }\r
2725 \r
2726 void perrormod (const char * s)\r
2727 {\r
2728   printf("`%s': %s\n", s, strerror(errno));\r
2729 }\r
2730 \r
2731 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */\r
2732 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */\r
2733 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */\r
2734 /* this is then undone in tex3.c both for fopen input and output */\r
2735 /* not ideal, since pseudo name appears in log and in error messages ... */\r
2736 \r
2737 void hidetwiddle (char *tname)\r
2738 {\r
2739   char *s = tname;\r
2740 \r
2741 #ifdef DEBUGTWIDDLE\r
2742   if (trace_flag)\r
2743     printf("Hidetwiddle %s", tname);\r
2744 #endif\r
2745 \r
2746   while (*s != '\0')\r
2747   {\r
2748     if (*s == '~' && pseudo_tilde != 0)\r
2749       *s = (char) pseudo_tilde;  /* typically 254 */\r
2750     else if (*s == ' ' && pseudo_space != 0)\r
2751       *s = (char) pseudo_space;  /* typically 255 */\r
2752     s++;\r
2753   }\r
2754 \r
2755 #ifdef DEBUGTWIDDLE\r
2756   if (trace_flag)\r
2757     printf("=> %s\n", tname);\r
2758 #endif\r
2759 }\r
2760 \r
2761 void deslash_all (int ac, char **av)\r
2762 {\r
2763   char buffer[file_name_size];  \r
2764   char *s;\r
2765 \r
2766   if ((s = grabenv("TEXDVI")) != NULL)\r
2767     dvi_directory = s;\r
2768 \r
2769   if ((s = grabenv("TEXLOG")) != NULL)\r
2770     log_directory = s;\r
2771 \r
2772   if ((s = grabenv("TEXAUX")) != NULL)\r
2773     aux_directory = s;\r
2774 \r
2775   if ((s = grabenv("TEXFMT")) != NULL)\r
2776     fmt_directory = s;\r
2777 \r
2778   if ((s = grabenv("TEXPDF")) != NULL)\r
2779     pdf_directory = s;\r
2780 \r
2781   strcpy(buffer, av[0]);\r
2782 \r
2783   if ((s = strrchr(buffer, '\\')) != NULL)\r
2784     *(s + 1) = '\0';\r
2785   else if ((s = strrchr(buffer, '/')) != NULL)\r
2786     *(s + 1) = '\0';\r
2787   else if ((s = strrchr(buffer, ':')) != NULL)\r
2788     *(s + 1) = '\0';\r
2789 \r
2790   s = buffer + strlen(buffer) - 1;\r
2791 \r
2792   if (*s == '\\' || *s == '/')\r
2793     *s = '\0';\r
2794 \r
2795   if (strcmp(dvi_directory, "") != 0)\r
2796     flush_trailing_slash(dvi_directory);\r
2797 \r
2798   if (strcmp(log_directory, "") != 0)\r
2799     flush_trailing_slash(log_directory);\r
2800 \r
2801   if (strcmp(aux_directory, "") != 0)\r
2802     flush_trailing_slash(aux_directory);\r
2803 \r
2804   if (strcmp(fmt_directory, "") != 0)\r
2805     flush_trailing_slash(fmt_directory);\r
2806 \r
2807   if (strcmp(pdf_directory, "") != 0)\r
2808     flush_trailing_slash(pdf_directory);\r
2809 \r
2810   if (deslash)\r
2811   {\r
2812     if (strcmp(dvi_directory, "") != 0)\r
2813       unixify(dvi_directory);\r
2814     \r
2815     if (strcmp(log_directory, "") != 0)\r
2816       unixify(log_directory);\r
2817 \r
2818     if (strcmp(aux_directory, "") != 0)\r
2819       unixify(aux_directory);\r
2820 \r
2821     if (strcmp(fmt_directory, "") != 0)\r
2822       unixify(fmt_directory);\r
2823 \r
2824     if (strcmp(pdf_directory, "") != 0)\r
2825       unixify(pdf_directory);\r
2826   }\r
2827 \r
2828   format_spec = false;\r
2829 \r
2830   if (optind < ac && optind > 0)\r
2831   {\r
2832     if (deslash)\r
2833     {\r
2834       if (trace_flag)\r
2835         printf("deslash: k %d argv[k] %s (argc %d)\n", optind, av[optind], ac);\r
2836 \r
2837       unixify(av[optind]);\r
2838     }\r
2839 \r
2840     if (pseudo_tilde != 0 || pseudo_space != 0)\r
2841       hidetwiddle(av[optind]);\r
2842 \r
2843     if (*av[optind] == '&' || *av[optind] == '+')\r
2844     {\r
2845       format_spec = true;\r
2846       format_name = xstrdup(av[optind] + 1);\r
2847 \r
2848       if (optind + 1 < ac)\r
2849       {\r
2850         if (deslash)\r
2851         {\r
2852           if (trace_flag)\r
2853             printf("deslash: k %d argv[k] %s (argc %d)\n", optind + 1, av[optind + 1], ac);\r
2854 \r
2855           unixify(av[optind + 1]);\r
2856         }\r
2857 \r
2858         if (pseudo_tilde != 0 || pseudo_space != 0)\r
2859           hidetwiddle(av[optind + 1]);\r
2860       }\r
2861     }         \r
2862   }\r
2863 }\r
2864 \r
2865 int main_init (int ac, char ** av)\r
2866 {\r
2867   kpse_set_program_name(av[0], "dvipdfmx");\r
2868   xputenv("engine", "yandytex");\r
2869 \r
2870   if (sizeof(memory_word) != sizeof(halfword) * 2)\r
2871     printf("ERROR: Bad word size %ld!\n", sizeof(memory_word));\r
2872 \r
2873   start_time = clock();\r
2874   main_time  = start_time;\r
2875 \r
2876 /* reset all allocatable memory pointers to NULL - in case we drop out */\r
2877   main_memory = NULL;\r
2878   font_info   = NULL;\r
2879   str_pool    = NULL;\r
2880   str_start   = NULL;\r
2881 \r
2882 #ifdef ALLOCATESAVESTACK\r
2883   save_stack = NULL; \r
2884 #endif\r
2885 \r
2886 #ifdef ALLOCATEBUFFER\r
2887   buffer           = NULL;\r
2888   current_buf_size = 0;\r
2889   buffer           = realloc_buffer(initial_buf_size);\r
2890 #endif\r
2891 \r
2892   hyph_list  = NULL;\r
2893   hyph_word  = NULL;\r
2894   trie_taken = NULL;\r
2895   trie_hash  = NULL;\r
2896   trie_r     = NULL;\r
2897   trie_c     = NULL;\r
2898   trie_o     = NULL;\r
2899   trie_l     = NULL;\r
2900   trie_trc   = NULL;\r
2901   trie_tro   = NULL;\r
2902   trie_trl   = NULL;\r
2903 \r
2904   log_opened          = false;  /* so can tell whether opened */\r
2905   interaction         = -1;     /* default state => 3 */\r
2906   missing_characters  = 0;      /* none yet! */\r
2907   ignore_frozen       = false;  /* default is not to ignore 98/Oct/5 */\r
2908   suppress_f_ligs     = false;  /* default is not to ignore f-ligs */\r
2909 \r
2910   if (ac > 1 && !strncmp(av[1], "-Y", 2))\r
2911     reorder_arg_flag = false;\r
2912 \r
2913   if (reorder_arg_flag)\r
2914     reorderargs(ac, av);  \r
2915 \r
2916   if (init_commands(ac, av))\r
2917     return -1;\r
2918 \r
2919   check_fixed_align(trace_flag);\r
2920 \r
2921   format_file   = NULL;\r
2922   source_direct = NULL;\r
2923   dvi_file_name = NULL;\r
2924   log_file_name = NULL;\r
2925   pdf_file_name = NULL;\r
2926 \r
2927   first_pass_count  = 0;\r
2928   second_pass_count = 0;\r
2929   final_pass_count  = 0;\r
2930   paragraph_failed  = 0;\r
2931   single_line       = 0;\r
2932   overfull_hbox     = 0;\r
2933   underfull_hbox    = 0;\r
2934   overfull_vbox     = 0;\r
2935   underfull_vbox    = 0;\r
2936 \r
2937   if (trace_flag)\r
2938     puts("Entering main_init() (local.c).");\r
2939 \r
2940   probe_memory();\r
2941   ini_max_address = max_address;\r
2942 \r
2943   if (trace_flag)\r
2944     show_maximums(stdout);\r
2945 \r
2946   initial_memory();\r
2947   deslash_all(ac, av);\r
2948 \r
2949   if (format_spec && mem_spec_flag)\r
2950     puts("WARNING: Cannot change initial main_memory size when format specified");\r
2951 \r
2952   if (allocate_memory() != 0)\r
2953     return -1;\r
2954 \r
2955   check_alloc_align(trace_flag);\r
2956 \r
2957   if (trace_flag)\r
2958     puts("Leaving main_init() (local.c).");\r
2959 \r
2960   return 0;\r
2961 }\r
2962 \r
2963 #define CLK_TCK CLOCKS_PER_SEC\r
2964 \r
2965 void show_inter_val (clock_t inter_val)\r
2966 {\r
2967   int seconds, tenths, hundredth, thousands;\r
2968 \r
2969   if (inter_val >= CLK_TCK * 10)\r
2970   {\r
2971     tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK; \r
2972     seconds = tenths / 10; \r
2973     tenths = tenths % 10;\r
2974     printf("%d.%d", seconds, tenths);\r
2975   }\r
2976   else if (inter_val >= CLK_TCK)\r
2977   {\r
2978     hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;\r
2979     seconds = hundredth / 100;\r
2980     hundredth = hundredth % 100;\r
2981     printf("%d.%02d", seconds, hundredth);\r
2982   }\r
2983   else if (inter_val > 0)\r
2984   {\r
2985     thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;\r
2986     seconds = thousands / 1000;\r
2987     thousands = thousands % 1000;\r
2988     printf("%d.%03d", seconds, thousands);\r
2989   }\r
2990   else\r
2991     show_line("0", 0);\r
2992 }\r
2993 \r
2994 int endit(int flag)\r
2995 {\r
2996   finish_time = clock();\r
2997 \r
2998   if (missing_characters != 0)\r
2999     flag = 1;\r
3000 \r
3001   if (missing_characters)\r
3002     printf("! There %s %d missing character%s --- see log file\n",\r
3003       (missing_characters == 1) ? "was" : "were", missing_characters,\r
3004       (missing_characters == 1) ? "" : "s");\r
3005 \r
3006   if (free_memory() != 0)\r
3007     flag++;\r
3008 \r
3009   if (verbose_flag)\r
3010   {\r
3011     printf("Total ");\r
3012     show_inter_val(finish_time - start_time);\r
3013     printf(" sec (");\r
3014     show_inter_val(main_time - start_time);\r
3015     printf(" format load + ");\r
3016     show_inter_val(finish_time - main_time);\r
3017     printf(" processing) ");\r
3018 \r
3019     if (total_pages > 0)\r
3020     {\r
3021       show_inter_val((finish_time - main_time) / total_pages);\r
3022       printf(" sec per page.\n");\r
3023     }\r
3024   }\r
3025 \r
3026   return flag;\r
3027 }\r
3028 // printf control sequences' name\r
3029 void print_cs_name (FILE * output, int h)\r
3030 {\r
3031   int c, textof, n;\r
3032 \r
3033   memset(log_line, 0, sizeof(log_line));\r
3034 \r
3035   textof = hash[h].rh;\r
3036 \r
3037   if (textof == 0)\r
3038     return;\r
3039 \r
3040   c = sprintf(log_line, "(%d), ", h);\r
3041   n = length(textof);\r
3042 \r
3043   memmove(log_line + c, str_pool + str_start[textof], n);\r
3044   memmove(log_line + c + n, "\n", 2);\r
3045 \r
3046   if (output == stderr)\r
3047     show_line(log_line, 1);\r
3048   else if (output == stdout)\r
3049     show_line(log_line, 0);\r
3050   else\r
3051     fprintf(output, "%s", log_line);\r
3052 }\r
3053 // prototype\r
3054 int compare_strn (int, int, int, int);\r
3055 /* compare two csnames in qsort */\r
3056 int compare_cs (const void *cp1, const void *cp2)\r
3057 {\r
3058   int c1, c2, l1, l2, k1, k2, textof1, textof2;\r
3059 \r
3060   c1 = *(int *)cp1;\r
3061   c2 = *(int *)cp2;\r
3062   textof1 = hash[c1].rh;\r
3063   textof2 = hash[c2].rh;\r
3064   l1 = length(textof1);\r
3065   l2 = length(textof2);\r
3066   k1 = str_start[textof1];\r
3067   k2 = str_start[textof2];\r
3068 \r
3069   return compare_strn(k1, l1, k2, l2);\r
3070 }\r
3071 \r
3072 char * csused = NULL;\r
3073 \r
3074 /* Allocate table of indeces to allow sorting on csname */\r
3075 /* Allocate flags to remember which ones already listed at start */\r
3076 /* pass = 0 --> fmt   */\r
3077 /* pass = 1 --> after */\r
3078 void print_cs_names (FILE *output, int pass)\r
3079 {\r
3080   int h, k, ccount, repeatflag;\r
3081   int *cnumtable;\r
3082   int nfcs = frozen_control_sequence;\r
3083 \r
3084   if (pass == 0 && csused == NULL)\r
3085   {\r
3086     csused = (char *) malloc (nfcs);\r
3087 \r
3088     if (csused == NULL)\r
3089       return;\r
3090 \r
3091 #ifdef USEMEMSET\r
3092     memset(csused, 0, nfcs);\r
3093 #else\r
3094     for (h = 0; h < (hash_size + 780); h++)\r
3095       csused[h] = 0;\r
3096 #endif\r
3097   }\r
3098 \r
3099   ccount = 0;\r
3100 \r
3101   for (h = hash_base + 1; h < nfcs; h++)\r
3102   {\r
3103     if (pass == 1 && csused[h])\r
3104       continue;\r
3105 \r
3106     if (text(h) != 0)\r
3107     {\r
3108       if (pass == 0)\r
3109         csused[h] = 1;\r
3110 \r
3111       ccount++;\r
3112     }\r
3113   }\r
3114 \r
3115   sprintf(log_line, "\n%d %s multiletter control sequences:\n",\r
3116       ccount, (pass == 1) ? "new" : "");\r
3117 \r
3118   if (output == stderr)\r
3119     show_line(log_line, 1);\r
3120   else if (output == stdout)\r
3121     show_line(log_line, 0);\r
3122   else\r
3123     fprintf(output, "%s", log_line);\r
3124 \r
3125   if (ccount > 0)\r
3126   {\r
3127     cnumtable = (int *) malloc (ccount * sizeof(int));\r
3128 \r
3129     if (cnumtable == NULL)\r
3130       return;\r
3131 \r
3132     ccount = 0;\r
3133 \r
3134     for (h = hash_base + 1; h < nfcs; h++)\r
3135     {\r
3136       if (pass == 1 && csused[h])\r
3137         continue;\r
3138 \r
3139       if (hash[h].rh != 0)\r
3140         cnumtable[ccount++] = h;\r
3141     }\r
3142 \r
3143     //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);\r
3144 \r
3145     repeatflag = 0;\r
3146 \r
3147     for (k = 0; k < ccount; k++)\r
3148     {\r
3149       h = cnumtable[k];\r
3150 \r
3151       if (pass == 1 && csused[h])\r
3152         continue;\r
3153 \r
3154       print_cs_name(output, h);\r
3155     }\r
3156 \r
3157     sprintf(log_line, "\n");\r
3158 \r
3159     if (output == stderr)\r
3160       show_line(log_line, 1);\r
3161     else if (output == stdout)\r
3162       show_line(log_line, 0);\r
3163     else\r
3164       fprintf(output, "%s", log_line);\r
3165 \r
3166     free((void *)cnumtable);\r
3167   }\r
3168 \r
3169   if (pass == 1 && csused != NULL)\r
3170   {\r
3171     free(csused);\r
3172     csused = NULL;\r
3173   }\r
3174 }\r
3175 \r
3176 /* k1 and k2 are positions in string pool */\r
3177 /* l1 and l2 are lengths of strings */\r
3178 int compare_strn (int k1, int l1, int k2, int l2)\r
3179 {\r
3180   int c1, c2;\r
3181 \r
3182   while (l1 > 0 && l2 > 0)\r
3183   {\r
3184     c1 = str_pool[k1];\r
3185     c2 = str_pool[k2];\r
3186 \r
3187     if (c1 > c2)\r
3188       return 1;\r
3189     else if (c2 > c1)\r
3190       return -1;\r
3191 \r
3192     l1--; l2--;\r
3193     k1++; k2++;\r
3194   }\r
3195 \r
3196   if (l1 > 0)\r
3197     return 1;   /* first string longer */\r
3198   else if (l2 > 0)\r
3199     return -1; /* second string longer */\r
3200 \r
3201   return 0;         /* strings match */\r
3202 }\r
3203 /* compare two font names and their at sizes in qsort */\r
3204 int compare_fnt (const void * fp1, const void * fp2)\r
3205 {\r
3206   int f1, f2, l1, l2, k1, k2, s;\r
3207 \r
3208   f1 = *(short *)fp1;\r
3209   f2 = *(short *)fp2;\r
3210   l1 = length(font_name[f1]);\r
3211   l2 = length(font_name[f2]);\r
3212   k1 = str_start[font_name[f1]]; \r
3213   k2 = str_start[font_name[f2]]; \r
3214 \r
3215   s = compare_strn (k1, l1, k2, l2);\r
3216 \r
3217   if (s != 0)\r
3218     return s;\r
3219 \r
3220   if (font_size[f1] > font_size[f2])\r
3221     return 1;\r
3222   else if (font_size[f1] < font_size[f2])\r
3223     return -1;\r
3224 \r
3225   return 0;         /* should not ever get here */\r
3226 }\r
3227 /* compare two font names */\r
3228 int compare_fnt_name (int f1, int f2)\r
3229 {\r
3230   int l1, l2, k1, k2, s;\r
3231 \r
3232   l1 = length(font_name[f1]);\r
3233   l2 = length(font_name[f2]); \r
3234   k1 = str_start[font_name[f1]]; \r
3235   k2 = str_start[font_name[f2]]; \r
3236 \r
3237   s = compare_strn (k1, l1, k2, l2);\r
3238 \r
3239   return s;\r
3240 }\r
3241 /* decode checksum information */\r
3242 const unsigned long checkdefault = 0x59265920;\r
3243 int decode_fourty (unsigned long checksum, char *codingvector)\r
3244 {\r
3245   int c;\r
3246   int k;\r
3247 \r
3248   if (checksum == 0)\r
3249   {\r
3250     strcpy(codingvector, "unknwn");\r
3251     return 1;\r
3252   }\r
3253   else if ((checksum >> 8) == (checkdefault >> 8))\r
3254   {\r
3255     strcpy (codingvector, "fixed ");\r
3256     return 1;\r
3257   }\r
3258   else\r
3259   {\r
3260     for (k = 0; k < 6; k++)\r
3261     {\r
3262       c = (int) (checksum % 40);\r
3263       checksum = checksum / 40;\r
3264       \r
3265       if (c <= 'z' - 'a')\r
3266         c = c + 'a';\r
3267       else if (c < 36)\r
3268         c = (c + '0') - ('z' - 'a') - 1;\r
3269       else if (c == 36)\r
3270         c = '-';\r
3271       else if (c == 37)\r
3272         c = '&';\r
3273       else if (c == 38)\r
3274         c = '_';\r
3275       else\r
3276         c = '.';\r
3277       \r
3278       codingvector[5-k] = (char) c;\r
3279     }\r
3280 \r
3281     codingvector[6] = '\0';\r
3282   }\r
3283 \r
3284   return 0;\r
3285 }\r
3286 \r
3287 double sclpnt (long x)\r
3288 {\r
3289   double pt;\r
3290 \r
3291   pt = (double) x / 65536.0;\r
3292   pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;\r
3293 \r
3294   return (pt);\r
3295 }\r
3296 \r
3297 void dvi_font_show (internal_font_number f, int suppressname)\r
3298 {\r
3299   int a, l, k, n;\r
3300   unsigned long checksum;\r
3301   char checksumvector[8];\r
3302   char buffer[32];\r
3303 \r
3304   putc(' ', log_file);\r
3305 \r
3306   if (suppressname == 0)\r
3307   {\r
3308     a = length(font_area[f]);\r
3309     l = length(font_name[f]);\r
3310 \r
3311     k = str_start[font_area[f]];\r
3312 \r
3313     memcpy(buffer, str_pool + k, length(font_area[f]));\r
3314     fwrite(buffer, sizeof(char), length(font_area[f]), log_file);\r
3315 \r
3316     k = str_start[font_name[f]];\r
3317 \r
3318     memcpy(buffer, str_pool + k, length(font_name[f]));\r
3319     fwrite(buffer, sizeof(char), length(font_name[f]), log_file);\r
3320   }\r
3321   else a = l = 0;\r
3322 \r
3323   for (k = a + l; k < 16; k++)\r
3324     putc(' ', log_file);\r
3325 \r
3326   sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));\r
3327   fputs(buffer, log_file);\r
3328 \r
3329   if (suppressname == 0)\r
3330   {\r
3331     n = strlen(buffer);\r
3332 \r
3333     for (k = n; k < 16; k++)\r
3334       putc(' ', log_file);\r
3335 \r
3336     checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;\r
3337     decode_fourty(checksum, checksumvector);\r
3338     fprintf(log_file, "encoding: %s..", checksumvector);\r
3339   }\r
3340 \r
3341   putc('\n', log_file);\r
3342 }\r
3343 /* Allocate table of indeces to allow sorting on font name */\r
3344 void show_font_info (void)\r
3345 {\r
3346   int k, m, fcount, repeatflag;\r
3347   short *fnumtable;\r
3348 \r
3349   fcount = 0;\r
3350 \r
3351   for (k = 1; k <= font_ptr; k++)\r
3352     if (font_used[k])\r
3353       fcount++;\r
3354 \r
3355   if (fcount == 0)\r
3356     return;\r
3357 \r
3358   fnumtable = (short *) malloc(fcount * sizeof(short));\r
3359 \r
3360   fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");\r
3361 \r
3362   fcount = 0;\r
3363 \r
3364   for (k = 1; k <= font_ptr; k++) \r
3365     if (font_used[k])\r
3366       fnumtable[fcount++] = (short) k;\r
3367 \r
3368   qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);\r
3369 \r
3370   repeatflag = 0;\r
3371 \r
3372   for (m = 0; m < fcount; m++)\r
3373   {\r
3374     if (m > 0)\r
3375     {\r
3376       if (compare_fnt_name(fnumtable[m - 1], fnumtable[m]) == 0)\r
3377         repeatflag = 1;\r
3378       else\r
3379         repeatflag = 0;\r
3380     }\r
3381 \r
3382     dvi_font_show(fnumtable[m], repeatflag);\r
3383   }\r
3384 \r
3385   free((void *)fnumtable);\r
3386 }\r