OSDN Git Service

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