1/* 2 See license.txt in the root of this project. 3*/ 4 5# include "luametatex.h" 6 7fileio_state_info lmt_fileio_state = { 8 .io_buffer = NULL, 9 .io_buffer_data = { 10 .minimum = min_buffer_size, 11 .maximum = max_buffer_size, 12 .size = siz_buffer_size, 13 .step = stp_buffer_size, 14 .allocated = 0, 15 .itemsize = sizeof(unsigned char), 16 .top = 0, 17 .ptr = 0, 18 .initial = memory_data_unset, 19 .offset = 0, 20 .extra = 0, 21 }, 22 .io_first = 0, 23 .io_last = 0, 24 .name_in_progress = 0, 25 .log_opened = 0, 26 .job_name = NULL, 27 .log_name = NULL, 28 .fmt_name = NULL 29}; 30 31/*tex 32 33 Once \TEX\ is working, you should be able to diagnose most errors with the |\show| commands and 34 other diagnostic features. Because we have made some internal changes the optional debug interface 35 has been removed. 36 37*/ 38 39# define reserved_io_buffer_slots 256 40 41void tex_initialize_fileio_state(void) 42{ 43 int size = lmt_fileio_state.io_buffer_data.minimum; 44 lmt_fileio_state.io_buffer = aux_allocate_clear_array(sizeof(unsigned char), size, reserved_io_buffer_slots); 45 if (lmt_fileio_state.io_buffer) { 46 lmt_fileio_state.io_buffer_data.allocated = size; 47 } else { 48 tex_overflow_error("buffer", size); 49 } 50} 51 52bool tex_room_in_buffer(int top) 53{ 54 /*tex Beware: |top| can exceed the old size plus the step. */ 55 if (top > lmt_fileio_state.io_buffer_data.top) { 56 lmt_fileio_state.io_buffer_data.top = top; 57 if (top > lmt_fileio_state.io_buffer_data.allocated) { 58 unsigned char *tmp = NULL; 59 if (top <= lmt_fileio_state.io_buffer_data.size) { 60 if (lmt_fileio_state.io_buffer_data.allocated + lmt_fileio_state.io_buffer_data.step > top) { 61 top = lmt_fileio_state.io_buffer_data.allocated + lmt_fileio_state.io_buffer_data.step; 62 if (top > lmt_fileio_state.io_buffer_data.size) { 63 top = lmt_fileio_state.io_buffer_data.size; 64 } 65 } 66 if (top > lmt_fileio_state.io_buffer_data.allocated) { 67 lmt_fileio_state.io_buffer_data.allocated = top; 68 tmp = aux_reallocate_array(lmt_fileio_state.io_buffer, sizeof(unsigned char), top, reserved_io_buffer_slots); 69 lmt_fileio_state.io_buffer = tmp; 70 } 71 } 72 lmt_run_memory_callback("buffer", tmp ? 1 : 0); 73 if (! tmp) { 74 tex_overflow_error("buffer", top); 75 return false; 76 } 77 } 78 } 79 return true; 80} 81 82static int tex_aux_open_outfile(FILE **f, const char *name, const char *mode) 83{ 84 FILE *res = aux_utf8_fopen(name, mode); 85 if (res) { 86 *f = res; 87 return 1; 88 } 89 return 0; 90} 91 92/*tex 93 94 We conform to the way \WEBC\ does handle trailing tabs and spaces. This decade old behaviour 95 was changed in September 2017 and can introduce compatibility issues in existing workflows. 96 Because we don't want too many differences with upstream \TEX live we just follow up on that 97 patch and it's up to macro packages to deal with possible issues (which can be done via the 98 usual callbacks. One can wonder why we then still prune spaces but we leave that to the reader. 99 100 Patched original comment: 101 102 Make last be one past the last non-space character in \quote {buffer}, ignoring line 103 terminators (but not, e.g., tabs). This is because we are supposed to treat this like a line of 104 TeX input. Although there are pathological cases (|SP CR SC CR|) where this differs from 105 input_line below, and from previous behavior of removing all whitespace, the simplicity of 106 removing all trailing line terminators seems more in keeping with actual command line 107 processing. 108 109 The |IS_SPC_OR_EOL| macro deals with space characters (|SPACE 32|) and newlines (|CR| and |LF|) 110 and no longer looks at tabs (|TAB 9|). 111 112*/ 113 114/* 115 The terminal input code is gone as is the read related code (that had already been nicely 116 cleaned up and abstracted but that is the price we pay for stepwise progress. That code is 117 still in the git repository of course. 118 119 At some point I might do the same as we do in mplib: four callbacks for open, close, read 120 and write (in which case the log goes via write). Part of the management is them moved to 121 \LUA\ and we save a lookup. 122 123 When I adapted the code in this module and the one dealing with errors, I decided to delegate 124 all interaction to \LUA, also because the sometimes tight integration in the scanning and 125 expansion mechanisms. In the 2021 TeX tuneup there have been some patches in the interaction 126 code and some remarks ring a bell: especially the relation between offering feedback and 127 waiting for input. However, because we delegate to \LUA, the engine is no longer responsible 128 for what the macro package lets the user do in case of an error. For instance, in \CONTEXT\ we 129 just abort the run: it makes no sense to carry on the wrong way. Computers are fast enough for 130 a \quotation {Fix and run again.} approach. But we do offer the message and optional help as 131 cue. On the agenda is a further abstraction of error handling. This deviation is fine as we 132 obey Don's wish to not call it \TEX\ but instead add some more letters to the name. 133 134*/ 135 136int tex_lua_a_open_in(const char *fn) 137{ 138 int callback_id = lmt_callback_defined(open_data_file_callback); 139 if (callback_id > 0) { 140 int k = lmt_run_and_save_callback(lmt_lua_state.lua_instance, callback_id, "S->", fn); 141 lmt_input_state.in_stack[lmt_input_state.cur_input.index].input_file_callback_id = k; 142 return k > 0; 143 } else { 144 tex_emergency_message("startup error", "missing open_data_file callback"); 145 tex_emergency_exit(); 146 return 0; 147 } 148} 149 150void tex_lua_a_close_in() 151{ 152 int k = lmt_input_state.in_stack[lmt_input_state.cur_input.index].input_file_callback_id; 153 if (k > 0) { 154 lmt_run_saved_callback_close(lmt_lua_state.lua_instance, k); 155 lmt_destroy_saved_callback(lmt_lua_state.lua_instance, k); 156 lmt_input_state.in_stack[lmt_input_state.cur_input.index].input_file_callback_id = 0; 157 } 158} 159 160/*tex 161 162 Binary input and output are done with \CCODE's ordinary procedures, so we don't have to make 163 any other special arrangements for binary \IO. Text output is also easy to do with standard 164 routines. The treatment of text input is more difficult, however, because of the necessary 165 translation to |unsigned char| values. \TEX's conventions should be efficient, and they should 166 blend nicely with the user's operating environment. 167 168 Input from text files is read one line at a time, using a routine called |lua_input_ln|. This 169 function is defined in terms of global variables called |buffer|, |first|, and |last| that will 170 be described in detail later; for now, it suffices for us to know that |buffer| is an array of 171 |unsigned char| values, and that |first| and |last| are indices into this array representing 172 the beginning and ending of a line of text. 173 174 The lines of characters being read: |buffer|, the first unused position in |first|, the end of 175 the line just input |last|, the largest index used in |buffer|: |max_buf_stack|. 176 177 The |lua_input_ln| function brings the next line of input from the specified file into available 178 positions of the buffer array and returns the value |true|, unless the file has already been 179 entirely read, in which case it returns |false| and sets |last:=first|. In general, the 180 |unsigned char| numbers that represent the next line of the file are input into |buffer[first]|, 181 |buffer[first + 1]|, \dots, |buffer[last - 1]|; and the global variable |last| is set equal to 182 |first| plus the length of the line. Trailing blanks are removed from the line; thus, either 183 |last = first| (in which case the line was entirely blank) or |buffer[last - 1] <> " "|. 184 185 An overflow error is given, however, if the normal actions of |lua_input_ln| would make |last 186 >= buf_size|; this is done so that other parts of \TEX\ can safely look at the contents of 187 |buffer[last+1]| without overstepping the bounds of the |buffer| array. Upon entry to 188 |lua_input_ln|, the condition |first < buf_size| will always hold, so that there is always room 189 for an \quote {empty} line. 190 191 The variable |max_buf_stack|, which is used to keep track of how large the |buf_size| parameter 192 must be to accommodate the present job, is also kept up to date by |lua_input_ln|. 193 194 If the |bypass_eoln| parameter is |true|, |lua_input_ln| will do a |get| before looking at the 195 first character of the line; this skips over an |eoln| that was in |f^|. The procedure does not 196 do a |get| when it reaches the end of the line; therefore it can be used to acquire input from 197 the user's terminal as well as from ordinary text files. 198 199 Since the inner loop of |lua_input_ln| is part of \TEX's \quote {inner loop} --- each character 200 of input comes in at this place --- it is wise to reduce system overhead by making use of 201 special routines that read in an entire array of characters at once, if such routines are 202 available. 203 204*/ 205 206int tex_lua_input_ln(void) /*tex |bypass_eoln| was not used */ 207{ 208 int callback_id = lmt_input_state.in_stack[lmt_input_state.cur_input.index].input_file_callback_id; 209 if (callback_id > 0) { 210 lua_State *L = lmt_lua_state.lua_instance; 211 int last_ptr = 0; 212 lmt_fileio_state.io_last = lmt_fileio_state.io_first; 213 last_ptr = lmt_run_saved_callback_line(L, callback_id, lmt_fileio_state.io_first); 214 if (last_ptr < 0) { 215 return 0; 216 } else if (last_ptr > 0) { 217 lmt_fileio_state.io_last = last_ptr; 218 if (last_ptr > lmt_fileio_state.io_buffer_data.top) { 219 lmt_fileio_state.io_buffer_data.top = last_ptr; 220 } 221 } 222 return 1; 223 } else { 224 return 0; 225 } 226} 227 228/*tex 229 230 We need a special routine to read the first line of \TEX\ input from the user's terminal. 231 This line is different because it is read before we have opened the transcript file; there is 232 sort of a \quote {chicken and egg} problem here. If the user types |\input paper| on the first 233 line, or if some macro invoked by that line does such an |\input|, the transcript file will be 234 named |paper.log|; but if no |\input| commands are performed during the first line of terminal 235 input, the transcript file will acquire its default name |texput.log|. (The transcript file 236 will not contain error messages generated by the first line before the first |\input| command.) 237 238 The first line is special also because it may be read before \TEX\ has input a format file. In 239 such cases, normal error messages cannot yet be given. The following code uses concepts that 240 will be explained later. 241 242 Different systems have different ways to get started. But regardless of what conventions are 243 adopted, the routine that initializes the terminal should satisfy the following specifications: 244 245 \startitemize[n] 246 247 \startitem 248 It should open file |term_in| for input from the terminal. 249 \stopitem 250 251 \startitem 252 If the user has given a command line, this line should be considered the first line of 253 terminal input. Otherwise the user should be prompted with |**|, and the first line of 254 input should be whatever is typed in response. 255 \stopitem 256 257 \startitem 258 The first line of input, which might or might not be a command line, should appear in 259 locations |first| to |last-1| of the |buffer| array. 260 \stopitem 261 262 \startitem 263 The global variable |loc| should be set so that the character to be read next by \TEX\ 264 is in |buffer[loc]|. This character should not be blank, and we should have |loc < last|. 265 \stopitem 266 267 \stopitemize 268 269 It may be necessary to prompt the user several times before a non-blank line comes in. The 270 prompt is |**| instead of the later |*| because the meaning is slightly different: |\input| 271 need not be typed immediately after |**|.) 272 273 The following code does the required initialization. If anything has been specified on the 274 command line, then |t_open_in| will return with |last > first|. 275 276 This code has been adapted and we no longer ask for a name. It makes no sense because one needs 277 to initialize the primitives and backend anyway and no one is going to do that interactively. 278 Of course one can implement a session in \LUA. We keep the \TEX\ trick to push the name into 279 the input buffer and then exercise an |\input| which ensures proper housekeeping. There is a 280 bit overkill in the next function but for now we keep it (as reference). 281 282 For a while copying the argument to th ebuffer lived in the engine lib but it made no sense 283 to duplicate code, so now it's here. Anyway, the following does no longer apply: 284 285 \startquotation 286 This is supposed to open the terminal for input, but what we really do is copy command line 287 arguments into \TEX's buffer, so it can handle them. If nothing is available, or we've been 288 called already (and hence, |argc == 0|), we return with |last = first|. 289 \stopquotation 290 291 In \LUAMETATEX\ we don't really have a terminal. In the \LUATEX\ precursor we used to append 292 all the remaining arguments but now we just take the first one. If one wants filenames with 293 spaces \unknown\ use quotes. Keep in mind that original \TEX\ permits this: 294 295 \starttyping 296 tex ... filename \\hbox{!} \\end 297 \stoptyping 298 299 But we don't follow that route in the situation where \LUA\ is mostly in charge of passing 300 input from files and the console. 301 302 In the end I went for an easier solution: just pass the name to the file reader. But we keep 303 this as nostalgic reference to how \TEX\ originally kin dof did these things. 304 305 \starttyping 306 int input_file_name_pushed(void) 307 { 308 const char *ptr = engine_input_filename(); 309 if (ptr) { 310 int len = strlen(ptr); 311 fileio_state.io_buffer[fileio_state.io_first] = 0; 312 if (len > 0 && room_in_buffer(len + 1)) { 313 // We cannot use strcat, because we have multibyte UTF-8 input. Hm, why not. 314 fileio_state.io_last= fileio_state.io_first; 315 while (*ptr) { 316 fileio_state.io_buffer[fileio_state.io_last++] = (unsigned char) * (ptr++); 317 } 318 // Backtrack over spaces and newlines. 319 for ( 320 --fileio_state.io_last; 321 fileio_state.io_last >= fileio_state.io_first && IS_SPC_OR_EOL(fileio_state.io_buffer[fileio_state.io_last]); 322 --fileio_state.io_last 323 ); 324 // Terminate the string. 325 fileio_state.io_buffer[++fileio_state.io_last] = 0; 326 // One more time, this time converting to \TEX's internal character representation. 327 if (fileio_state.io_last > fileio_state.io_first) { 328 input_state.cur_input.loc = fileio_state.io_first; 329 while ((input_state.cur_input.loc < fileio_state.io_last) && (fileio_state.io_buffer[input_state.cur_input.loc] == ' ')) { 330 ++input_state.cur_input.loc; 331 } 332 if (input_state.cur_input.loc < fileio_state.io_last) { 333 input_state.cur_input.limit = fileio_state.io_last; 334 fileio_state.io_first = fileio_state.io_last + 1; 335 } 336 if (input_state.cur_input.loc < input_state.cur_input.limit) { 337 return 1; 338 } 339 } 340 } 341 } 342 fileio_state.io_first = 1; 343 fileio_state.io_last = 1; 344 return 0; 345 } 346 \stopttyping 347 348 It's this kind of magic that can take lots of time to play with and figure out, also because 349 we cannot break expectations too much. 350 351*/ 352 353/*tex 354 355 Per June 22 2020 the terminal code is gone. See |texlegacy.c| for the old, already adapted 356 long ago, code. It was already shedulded for removal a while. We only keep the update. 357 358*/ 359 360void tex_terminal_update(void) /* renamed, else conflict in |lmplib|. */ 361{ 362 fflush(stdout); 363} 364 365/*tex 366 367 It's time now to fret about file names. Besides the fact that different operating systems treat 368 files in different ways, we must cope with the fact that completely different naming conventions 369 are used by different groups of people. The following programs show what is required for one 370 particular operating system; similar routines for other systems are not difficult to devise. 371 372 \TEX\ assumes that a file name has three parts: the name proper; its \quote {extension}; and a 373 \quote {file area} where it is found in an external file system. The extension of an input file 374 or a write file is assumed to be |.tex| unless otherwise specified; it is |transcript_extension| 375 on the transcript file that records each run of \TEX; it is |.tfm| on the font metric files that 376 describe characters in the fonts \TEX\ uses; it is |.dvi| on the output files that specify 377 typesetting information; and it is |format_extension| on the format files written by \INITEX\ 378 to initialize \TEX. The file area can be arbitrary on input files, but files are usually output 379 to the user's current area. 380 381 Simple uses of \TEX\ refer only to file names that have no explicit extension or area. For 382 example, a person usually says |\input paper| or |\font \tenrm = helvetica| instead of |\input 383 {paper.new}| or |\font \tenrm = {test}|. Simple file names are best, because they make the \TEX\ 384 source files portable; whenever a file name consists entirely of letters and digits, it should be 385 treated in the same way by all implementations of \TEX. However, users need the ability to refer 386 to other files in their environment, especially when responding to error messages concerning 387 unopenable files; therefore we want to let them use the syntax that appears in their favorite 388 operating system. 389 390 The following procedures don't allow spaces to be part of file names; but some users seem to like 391 names that are spaced-out. System-dependent changes to allow such things should probably be made 392 with reluctance, and only when an entire file name that includes spaces is \quote {quoted} somehow. 393 394 Here are the global values that file names will be scanned into. 395 396 \starttyping 397 strnumber cur_name; 398 strnumber cur_area; 399 strnumber cur_ext; 400 \stoptyping 401 402 The file names we shall deal with have the following structure: If the name contains |/| or |:| 403 (for Amiga only), the file area consists of all characters up to and including the final such 404 character; otherwise the file area is null. If the remaining file name contains |.|, the file 405 extension consists of all such characters from the last |.| to the end, otherwise the file 406 extension is null. 407 408 We can scan such file names easily by using two global variables that keep track of the 409 occurrences of area and extension delimiters: 410 411 Input files that can't be found in the user's area may appear in a standard system area called 412 |TEX_area|. Font metric files whose areas are not given explicitly are assumed to appear in a 413 standard system area called |TEX_font_area|. These system area names will, of course, vary from 414 place to place. 415 416 This whole model has been adapted a little but we do keep the |area|, |name|, |ext| distinction 417 for now although we don't use the string pool. 418 419*/ 420 421static char *tex_aux_pack_file_name(char *s, int l, const char *name, const char *ext) 422{ 423 const char *fn = (char *) s; 424 if ((! fn) || (l <= 0)) { 425 fn = name; 426 } 427 if (! fn) { 428 return NULL; 429 } else if (! ext) { 430 return lmt_memory_strdup(fn); 431 } else { 432 int e = -1; 433 for (int i = 0; i < l; i++) { 434 if (IS_DIR_SEP(fn[i])) { 435 e = -1; 436 } else if (fn[i] == '.') { 437 e = i; 438 } 439 } 440 if (e >= 0) { 441 return lmt_memory_strdup(fn); 442 } else { 443 char *f = lmt_memory_malloc(strlen(fn) + strlen(ext) + 1); 444 if (f) { 445 sprintf(f, "%s%s", fn, ext); 446 } 447 return f; 448 } 449 } 450} 451 452/*tex 453 454 Here is a routine that manufactures the output file names, assuming that |job_name <> 0|. It 455 ignores and changes the current settings of |cur_area| and |cur_ext|; |s = transcript_extension|, 456 |".dvi"|, or |format_extension| 457 458 The packer does split the basename every time but isn't called that often so we can use it in 459 the checker too. 460 461*/ 462 463static char *tex_aux_pack_job_name(const char *e, int keeppath, int keepsuffix) 464{ 465 char *n = lmt_fileio_state.job_name; 466 int ln = (n) ? (int) strlen(n) : 0; 467 if (! ln) { 468 tex_fatal_error("bad jobname"); 469 return NULL; 470 } else { 471 int le = (e) ? (int) strlen(e) : 0; 472 int f = -1; /* first */ 473 int l = -1; /* last */ 474 char *fn = NULL; 475 int k = 0; 476 for (int i = 0; i < ln; i++) { 477 if (IS_DIR_SEP(n[i])) { 478 f = i; 479 l = -1; 480 } else if (n[i] == '.') { 481 l = i; 482 } 483 } 484 if (keeppath) { 485 f = 0; 486 } else if (f < 0) { 487 f = 0; 488 } else { 489 f += 1; 490 } 491 if (keepsuffix || l < 0) { 492 l = ln; 493 } 494 fn = (char*) lmt_memory_malloc((l - f) + le + 2); /* a bit too much */ 495 if (fn) { 496 for (int i = f; i < l; i++) { 497 fn[k++] = n[i]; 498 } 499 for (int i = 0; i < le; i++) { 500 fn[k++] = e[i]; 501 } 502 fn[k] = 0; 503 } 504 return fn; 505 } 506} 507 508/*tex 509 510 The following comment is obsolete but we keep it as reference because it tells some history. 511 512 \startquotation 513 Because the format is zipped we read and write dump files through zlib. Earlier versions recast 514 |*f| from |FILE *| to |gzFile|, but there is no guarantee that these have the same size, so a 515 static variable is needed. 516 517 We no longer do byte-swapping so formats are generated for the system and not shared. It 518 actually slowed down loading of the format on the majority of used platforms (intel). 519 520 A \CONTEXT\ format is uncompressed some 16 MB but that used to be over 30MB due to more 521 (preallocated) memory usage. A compressed format is 11 MB so the saving is not that much. If 522 we were in lua I'd load the whole file in one go and use a fast decompression after which we 523 could access the bytes in memory. But it's not worth the trouble. 524 525 Tests has shown that a level 3 compression is the most optimal tradeoff between file size and 526 load time. 527 528 So, in principle we can undefine |FMT_COMPRESSION| below and experiment a bit with it. With 529 SSD's it makes no dent, but on a network it still might. 530 531 Per end May 2019 the |FMT_COMPRESSION| branch is gone so that we can simplify the opener and 532 closer. 533 \stopquotation 534 535*/ 536 537void tex_check_fmt_name(void) 538{ 539 if (lmt_engine_state.dump_name) { 540 char *tmp = lmt_fileio_state.job_name; 541 lmt_fileio_state.job_name = lmt_engine_state.dump_name; 542 lmt_fileio_state.fmt_name = tex_aux_pack_job_name(format_extension, 1, 0); 543 lmt_fileio_state.job_name = tmp; 544 } else if (lmt_main_state.run_state != initializing_state) { 545 /*tex For |dump_name| to be NULL is a bug. */ 546 tex_emergency_message("startup error", "no format file given, quitting"); 547 tex_emergency_exit(); 548 } 549} 550 551void tex_check_job_name(char * fn) 552{ 553 if (! lmt_fileio_state.job_name) { 554 if (lmt_engine_state.startup_jobname) { 555 lmt_fileio_state.job_name = lmt_engine_state.startup_jobname; /* not freed here */ 556 lmt_fileio_state.job_name = tex_aux_pack_job_name(NULL, 0, 0); 557 } else if (fn) { 558 lmt_fileio_state.job_name = fn; 559 lmt_fileio_state.job_name = tex_aux_pack_job_name(NULL, 0, 0); /* not freed here */ 560 } else { 561 tex_emergency_message("startup warning", "using fallback jobname 'texput', continuing"); 562 lmt_fileio_state.job_name = lmt_memory_strdup("texput"); 563 } 564 } 565 if (! lmt_fileio_state.log_name) { 566 lmt_fileio_state.log_name = tex_aux_pack_job_name(transcript_extension, 0, 1); 567 } 568 if (! lmt_fileio_state.fmt_name) { 569 lmt_fileio_state.fmt_name = tex_aux_pack_job_name(format_extension, 0, 1); 570 } 571} 572 573/*tex 574 575 A messier routine is also needed, since format file names must be scanned before \TEX's 576 string mechanism has been initialized. We shall use the global variable |TEX_format_default| 577 to supply the text for default system areas and extensions related to format files. 578 579 Under \UNIX\ we don't give the area part, instead depending on the path searching that will 580 happen during file opening. Also, the length will be set in the main program. 581 582 \starttyping 583 char *TEX_format_default; 584 \stoptyping 585 586 This part of the program becomes active when a \quote {virgin} \TEX\ is trying to get going, 587 just after the preliminary initialization, or when the user is substituting another format file 588 by typing |&| after the initial |**| prompt. The buffer contains the first line of input in 589 |buffer[loc .. (last - 1)]|, where |loc < last| and |buffer[loc] <> " "|. 590 591*/ 592 593dumpstream tex_open_fmt_file(int writemode) 594{ 595 dumpstream f = NULL; 596 if (! lmt_fileio_state.fmt_name) { 597 /* this can't happen */ 598 tex_emergency_message("startup error", "no format output file '%s' given, quitting", emergency_fmt_name); 599 tex_emergency_exit(); 600 } else if (writemode) { 601 f = aux_utf8_fopen(lmt_fileio_state.fmt_name, FOPEN_WBIN_MODE); 602 if (! f) { 603 tex_emergency_message("startup error", "invalid format output file '%s' given, quitting", lmt_fileio_state.fmt_name); 604 tex_emergency_exit(); 605 } 606 } else { 607 int callbackid = lmt_callback_defined(find_format_file_callback); 608 if (callbackid > 0) { 609 char *fnam = NULL; 610 int test = lmt_run_callback(lmt_lua_state.lua_instance, callbackid, "S->R", lmt_fileio_state.fmt_name, &fnam); 611 if (test && fnam && strlen(fnam) > 0) { 612 lmt_memory_free(lmt_fileio_state.fmt_name); 613 lmt_fileio_state.fmt_name = fnam; 614 } else { 615 lmt_memory_free(fnam); 616 } 617 f = aux_utf8_fopen(lmt_fileio_state.fmt_name, FOPEN_RBIN_MODE); 618 if (! f) { 619 tex_emergency_message("startup error", "invalid format input file '%s' given, quitting", emergency_fmt_name); 620 tex_emergency_exit(); 621 } 622 } else { 623 /*tex For the moment we make this mandate! */ 624 tex_emergency_message("startup error", "missing find_format_file callback"); 625 tex_emergency_exit(); 626 } 627 } 628 return f; 629} 630 631void tex_close_fmt_file(dumpstream f) 632{ 633 if (f) { 634 fclose(f); 635 } 636} 637 638/*tex 639 640 The variable |name_in_progress| is used to prevent recursive use of |scan_file_name|, since the 641 |begin_name| and other procedures communicate via global variables. Recursion would arise only 642 by devious tricks like |\input \input f|; such attempts at sabotage must be thwarted. 643 Furthermore, |name_in_progress| prevents |\input| from being initiated when a font size 644 specification is being scanned. 645 646 Another variable, |job_name|, contains the file name that was first |\input| by the user. This 647 name is extended by |transcript_extension| and |.dvi| and |format_extension| in the names of 648 \TEX's output files. The fact if the transcript file been opened is registered in 649 |log_opened_global|. 650 651 Initially |job_name = 0|; it becomes nonzero as soon as the true name is known. We have 652 |job_name = 0| if and only if the |log| file has not been opened, except of course for a short 653 time just after |job_name| has become nonzero. 654 655 The full name of the log file is stored in |log_name|. The |open_log_file| routine is used to 656 open the transcript file and to help it catch up to what has previously been printed on the 657 terminal. 658 659*/ 660 661void tex_open_log_file(void) 662{ 663 if (! lmt_fileio_state.log_opened) { 664 int callback_id = lmt_callback_defined(find_log_file_callback); 665 if (callback_id > 0) { 666 char *filename = NULL; 667 int okay = 0; 668 tex_check_job_name(NULL); 669 okay = lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "S->R", lmt_fileio_state.log_name, &filename); 670 if (okay && filename && (strlen(filename) > 0)) { 671 lmt_memory_free(lmt_fileio_state.log_name); 672 lmt_fileio_state.log_name = filename; 673 } else { 674 lmt_memory_free(filename); 675 } 676 } else { 677 /*tex For the moment we make this mandate! */ 678 tex_emergency_message("startup error", "missing find_log_file callback"); 679 tex_emergency_exit(); 680 } 681 if (tex_aux_open_outfile(&lmt_print_state.logfile, lmt_fileio_state.log_name, FOPEN_W_MODE)) { 682 /*tex The previous |selector| setting is saved:*/ 683 int saved_selector = lmt_print_state.selector; 684 lmt_print_state.selector = logfile_selector_code; 685 lmt_fileio_state.log_opened = 1; 686 /*tex Again we resolve a callback id: */ 687 callback_id = lmt_callback_defined(start_run_callback); 688 /*tex There is no need to free |fn|! */ 689 if (callback_id == 0) { 690 tex_print_banner(); 691 /*tex Print the banner line, including current date and time. */ 692 tex_print_log_banner(); 693 /*tex Make sure bottom level is in memory. */ 694 lmt_input_state.input_stack[lmt_input_state.input_stack_data.ptr] = lmt_input_state.cur_input; 695 /*tex We don't have a first line so that code is gone. */ 696 tex_print_ln(); 697 } else if (callback_id > 0) { 698 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "->"); 699 } else { 700 tex_print_banner(); 701 } 702 /*tex should be done always */ 703 if (lmt_print_state.loggable_info) { 704 fprintf(lmt_print_state.logfile, "%s\n", lmt_print_state.loggable_info); 705 lmt_memory_free(lmt_print_state.loggable_info); 706 lmt_print_state.loggable_info = NULL; 707 } 708 switch (saved_selector) { 709 case no_print_selector_code : lmt_print_state.selector = logfile_selector_code; break; 710 case terminal_selector_code : lmt_print_state.selector = terminal_and_logfile_selector_code; break; 711 default : lmt_print_state.selector = saved_selector; break; 712 } 713 } else { 714 tex_emergency_message("startup error", "log file '%s' cannot be opened, quitting", emergency_log_name); 715 tex_emergency_exit(); 716 } 717 } 718} 719 720void tex_close_log_file(void) 721{ 722 fclose(lmt_print_state.logfile); 723 lmt_fileio_state.log_opened = 0; 724} 725 726/*tex 727 728 Let's turn now to the procedure that is used to initiate file reading when an |\input| command 729 is being processed. This function is used with |\\input| as well as in the start up. 730 731*/ 732 733void tex_start_input(char *fn, halfword at_end_of_file) 734{ 735 /*tex Set up |cur_file| and new level of input. */ 736 tex_begin_file_reading(); 737 if (! tex_lua_a_open_in(fn)) { 738 /*tex 739 Normally this is catched earler, as we have lookup callbacks but the first file, the 740 one passed on the command line can fall though this checking. 741 */ 742 tex_end_file_reading(); 743 tex_emergency_message("runtime error", "input file '%s' is not found, quitting", fn); 744 tex_emergency_exit(); 745 } 746 lmt_input_state.in_stack[lmt_input_state.in_stack_data.ptr].full_source_filename = fn; 747 lmt_input_state.cur_input.name = io_file_input_code; 748 lmt_input_state.in_stack[lmt_input_state.cur_input.index].at_end_of_file = at_end_of_file; 749 /*tex 750 |open_log_file| doesn't |show_context|, so |limit| and |loc| needn't be set to meaningful 751 values yet. 752 */ 753 tex_report_start_file((unsigned char *) fn); 754 ++lmt_input_state.open_files; 755 tex_terminal_update(); 756 lmt_input_state.cur_input.state = new_line_state; 757 /*tex 758 759 Read the first line of the new file. Here we have to remember to tell the |lua_input_ln| 760 routine not to start with a |get|. If the file is empty, it is considered to contain a 761 single blank line. 762 763 */ 764 lmt_input_state.input_line = 1; 765 tex_lua_input_ln(); 766 lmt_input_state.cur_input.limit = lmt_fileio_state.io_last; /*tex Was |firm_up_the_line();|. */ 767 if (end_line_char_inactive) { 768 --lmt_input_state.cur_input.limit; 769 } else { 770 lmt_fileio_state.io_buffer[lmt_input_state.cur_input.limit] = (unsigned char) end_line_char_par; 771 } 772 lmt_fileio_state.io_first = lmt_input_state.cur_input.limit + 1; 773 lmt_input_state.cur_input.loc = lmt_input_state.cur_input.start; 774} 775 776/*tex 777 778 In order to isolate the system-dependent aspects of file names, the system-independent parts of 779 \TEX\ are expressed in terms of three system-dependent procedures called |begin_name|, 780 |more_name|, and |end_name|. In essence, if the user-specified characters of the file name are 781 |c_1|\unknown|c_n|, the system-independent driver program does the operations 782 783 \starttyping 784 |begin_name|; 785 |more_name|(c_1); 786 ..... 787 |more_name|(c_n); 788 |end_name| 789 \stoptyping 790 791 These three procedures communicate with each other via global variables. Afterwards the file 792 name will appear in the string pool as three strings called |cur_name|, |cur_area|, and 793 |cur_ext|; the latter two are null (i.e., |""|), unless they were explicitly specified by the 794 user. 795 796 Actually the situation is slightly more complicated, because \TEX\ needs to know when the file 797 name ends. The |more_name| routine is a function (with side effects) that returns |true| on the 798 calls |more_name (c_1)|, \dots, |more_name (c_{n - 1})|. The final call |more_name(c_n)| returns 799 |false|; or, it returns |true| and the token following |c_n| is something like |\hbox| (i.e., 800 not a character). In other words, |more_name| is supposed to return |true| unless it is sure that 801 the file name has been completely scanned; and |end_name| is supposed to be able to finish the 802 assembly of |cur_name|, |cur_area|, and |cur_ext| regardless of whether |more_name (c_n)| 803 returned |true| or |false|. 804 805 This code has been adapted and the string pool is no longer used. We also don't ask for another 806 name on the console. 807 808*/ 809 810/*tex 811 812 And here's the second. The string pool might change as the file name is being scanned, since a 813 new |\csname| might be entered; therefore we keep |area_delimiter| and |ext_delimiter| relative 814 to the beginning of the current string, instead of assigning an absolute address like |pool_ptr| 815 to them. 816 817 Now let's consider the \quote {driver} routines by which \TEX\ deals with file names in a 818 system-independent manner. First comes a procedure that looks for a file name in the input by 819 calling |get_x_token| for the information. 820 821*/ 822 823char *tex_read_file_name(int optionalequal, const char * name, const char* ext) 824{ 825 halfword result; 826 if (optionalequal) { 827 tex_scan_optional_equals(); 828 } 829 do { 830 tex_get_x_token(); 831 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd); 832 if (cur_cmd == left_brace_cmd) { 833 result = tex_scan_toks_expand(1, NULL, 0, 0); 834 } else { 835 char quote = 0; 836 halfword p = get_reference_token(); 837 result = p; 838 while (1) { 839 switch (cur_cmd) { 840 case escape_cmd: 841 case left_brace_cmd: 842 case right_brace_cmd: 843 case math_shift_cmd: 844 case alignment_tab_cmd: 845 case parameter_cmd: 846 case superscript_cmd: 847 case subscript_cmd: 848 case letter_cmd: 849 case other_char_cmd: 850 switch (cur_chr) { 851 case double_quote: 852 if (quote == double_quote) { 853 goto DONE; 854 } else { 855 quote = double_quote; 856 } 857 break; 858 case single_quote: 859 if (quote == single_quote) { 860 goto DONE; 861 } else { 862 quote = single_quote; 863 } 864 break; 865 default: 866 p = tex_store_new_token(p, cur_tok); 867 } 868 break; 869 case spacer_cmd: 870 case end_line_cmd: 871 if (quote) { 872 p = tex_store_new_token(p, token_val(spacer_cmd, ' ')); 873 } else { 874 goto DONE; 875 } 876 case ignore_cmd: 877 break; 878 default: 879 tex_back_input(cur_tok); 880 goto DONE; 881 } 882 tex_get_x_token(); 883 } 884 } 885 DONE: 886 { 887 int l = 0; 888 char *s = tex_tokenlist_to_tstring(result, 1, &l, 0, 0, 0, 1, 1); /* single hashes */ 889 char *fn = s ? tex_aux_pack_file_name(s, l, name, ext) : NULL; 890 return fn; 891 } 892} 893 894void tex_print_file_name(unsigned char *name) 895{ 896 int must_quote = 0; 897 if (name) { 898 unsigned char *j = name; 899 while (*j) { 900 if (*j == ' ') { 901 must_quote = 1; 902 break; 903 } else { 904 j++; 905 } 906 } 907 } 908 if (must_quote) { 909 /* initial quote */ 910 tex_print_char('"'); 911 } 912 if (name) { 913 unsigned char *j = name; 914 while (*j) { 915 if (*j == '"') { 916 /* skip embedded quote, maybe escape */ 917 } else { 918 tex_print_char(*j); 919 } 920 j++; 921 } 922 } 923 if (must_quote) { 924 /* final quote */ 925 tex_print_char('"'); 926 } 927} 928 929void tex_report_start_file(unsigned char *name) 930{ 931 int callback_id = lmt_callback_defined(start_file_callback); 932 if (callback_id) { 933 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "S->", name); 934 } else { 935 tex_print_char('('); 936 tex_print_file_name((unsigned char *) name); 937 } 938} 939 940void tex_report_stop_file(void) 941{ 942 int callback_id = lmt_callback_defined(stop_file_callback); 943 if (callback_id) { 944 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "->"); 945 } else { 946 tex_print_char(')'); 947 } 948} 949 |