home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / unixtex-6.1b-src.lha / unixtex-6.1b / web2c / fontutil / gftodvi.ch < prev    next >
Encoding:
Text File  |  1993-11-06  |  26.6 KB  |  820 lines

  1. % gftodvi.ch for C compilation with web2c.
  2. %
  3. % History:
  4. % 01/20/90 Karl        New gftodvi.web (same version number).
  5. % 12/02/89 Karl Berry    To version 3.
  6. % Revision 1.7.1.5  86/02/01  15:29:58  richards
  7. %     Released again for MF 1.0 package
  8. % Revision 1.7.1.4  86/02/01  15:06:50  richards
  9. %     Added: <nl> at end of successful run
  10. % Revision 1.7.1.3  86/01/27  16:39:48  richards
  11. %     Fixed: syntax error in previous edits
  12. % Revision 1.7.1.2  86/01/27  15:55:58  richards
  13. %     Added: dvi_buf_type declaration and redefined dvi_buf[] in
  14. %            terms of it, so we can use it as a parameter to b_write_buf()
  15. % Revision 1.7.1.1  86/01/27  15:39:10  richards
  16. %     First edit to use new binary I/O routines
  17. % Revision 1.7  85/10/21  21:55:50  richards
  18. %     Released for GFtoDVI 1.7
  19. % Revision 1.3.7.1  85/10/18  22:59:01  richards
  20. %     Updated for GFtoDVI Version 1.7 (Distributed w/ MF84 Version 0.9999)
  21. % Revision 1.3.5.1  85/10/09  17:02:35  richards
  22. %     First draft to run at 1.5 level
  23. % Revision 1.3  85/05/27  21:15:30  richards
  24. %     Updated for GFtoDVI Version 1.3 (Distributed w/ MF84 Version 0.91)
  25. % Revision 1.2  85/04/25  19:33:30  richards
  26. %     Updated to GFtoDVI Version 1.2 (Distributed w/ MF84 Version 0.81)
  27. % Revision 1.1  85/03/03  21:47:17  richards
  28. %     Updated for GF utilities distributed with MF Version 0.77
  29. % Revision 1.0  84/12/16  22:38:22  richards
  30. %     Updated for GFtoDVI Version 1.0 (New GF file format)
  31. % Revision 0.6  84/12/05  13:32:01  richards
  32. %     Updated for GFtoDVI Version 0.6; merged in changes from sdcarl!rusty
  33. %     Note: still has BUGFIX in section 199 to keep GFtoDVI from trying
  34. %     to use non-existent characters in a gray font
  35. % Revision 0.3  84/11/17  23:51:56  richards
  36. %     Base version for GFtoDVI Version 0.3
  37.  
  38.  
  39. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  40. % [0] WEAVE: print changes only.
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. @x
  43. \pageno=\contentspagenumber \advance\pageno by 1
  44. @y
  45. \pageno=\contentspagenumber \advance\pageno by 1
  46. \let\maybe=\iffalse
  47. \def\title{GF$\,$\lowercase{to}$\,$DVI changes for C}
  48. @z
  49.  
  50. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  51. % [1] Change banner string.
  52. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  53. @x
  54. @d banner=='This is GFtoDVI, Version 3.0' {printed when the program starts}
  55. @y
  56. @d banner=='This is GFtoDVI, Version 3.0' {more is printed later}
  57. @z
  58.  
  59. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  60. % [3] Redirect output to term_out.
  61. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  62. @x
  63. @d print(#)==write(#)
  64. @d print_ln(#)==write_ln(#)
  65. @d print_nl(#)==@+begin write_ln; write(#);@+end
  66. @y
  67. @d term_out==stdout
  68. @d print(#)==write(term_out, #)
  69. @d print_ln(#)==write_ln(term_out, #)
  70. @d print_nl(#)==@+begin write_ln(term_out); write(term_out, #);@+end
  71. @z
  72.  
  73. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  74. % [still 3] Fix program header.
  75. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  76. @x
  77. @p program GF_to_DVI(@!output);
  78. label @<Labels in the outer block@>@/
  79. const @<Constants in the outer block@>@/
  80. type @<Types in the outer block@>@/
  81. var @<Globals in the outer block@>@/
  82. procedure initialize; {this procedure gets things started properly}
  83.   var @!i,@!j,@!m,@!n:integer; {loop indices for initializations}
  84.   begin print_ln(banner);@/
  85. @y
  86. @p program GF_to_DVI;
  87. const @<Constants in the outer block@>@/
  88. type @<Types in the outer block@>@/
  89. var @<Globals in the outer block@>@/
  90. procedure initialize; {this procedure gets things started properly}
  91.   var @!i,@!j,@!m,@!n:integer; {loop indices for initializations}
  92.       @<Local variables for initialization@>
  93.   begin
  94.     if argc > n_options + arg_options + 2
  95.     then begin
  96.       print_ln
  97.       ('Usage: gftodvi [-verbose] [-overflow-label-offset=<real>] <gf file>.');
  98. @.Usage: ...@>
  99.       uexit (1);
  100.     end;
  101.  
  102.     @<Initialize the option variables@>;
  103.     @<Parse arguments@>;
  104.     if verbose then begin
  105.       print (banner);
  106.       print_ln (version_string);
  107.     end;
  108. @z
  109.  
  110. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  111. % [4] Remove the final_end label.
  112. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  113. @x
  114. @ If the program has to stop prematurely, it goes to the
  115. `|final_end|'.
  116.  
  117. @d final_end=9999 {label for the end of it all}
  118.  
  119. @<Labels...@>=final_end;
  120. @y
  121. @ This module deleted, since it only defined the label |final_end|.
  122. @z
  123.  
  124. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  125. % [5] Make file_name_size match the system constant.
  126. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. @x
  128. @<Constants...@>=
  129. @y
  130. @d file_name_size==PATH_MAX {a file name shouldn't be longer than this}
  131. @<Constants...@>=
  132. @z
  133. @x
  134. @!file_name_size=50; {a file name shouldn't be longer than this}
  135. @y
  136. @z
  137.  
  138. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  139. % [8] Add newline to end of abort() message, and exit abnormally.
  140. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  141. @x
  142. @d abort(#)==@+begin print(' ',#); jump_out;@+end
  143. @y
  144. @d abort(#)==@+begin print_ln (#); uexit (1);@+end
  145. @z
  146.  
  147. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  148. % [8] Remove nonlocal goto.
  149. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  150. @x
  151. @p procedure jump_out;
  152. begin goto final_end;
  153. end;
  154. @y
  155. @p procedure jump_out;
  156. begin uexit(0);
  157. end;
  158. @z
  159.  
  160. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  161. % [11] The text_char type is used as an array index into xord.  The
  162. % default type `char' produces signed integers, which are bad array
  163. % indices in C.
  164. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  165. @x
  166. @d text_char == char {the data type of characters in text files}
  167. @y
  168. @d text_char == ASCII_code {the data type of characters in text files}
  169. @z
  170.  
  171. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  172. % [14] Allow any input character.
  173. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  174. @x
  175. for i:=0 to @'37 do xchr[i]:='?';
  176. for i:=@'177 to @'377 do xchr[i]:='?';
  177. @y
  178. for i:=1 to @'37 do xchr[i]:=chr(i);
  179. for i:=@'177 to @'377 do xchr[i]:=chr(i);
  180. @z
  181.  
  182.  
  183. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  184. % [15] Change `update_terminal' to `flush', `term_in' is stdin.
  185. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  186. @x
  187. Since the terminal is being used for both input and output, some systems
  188. need a special routine to make sure that the user can see a prompt message
  189. before waiting for input based on that message. (Otherwise the message
  190. may just be sitting in a hidden buffer somewhere, and the user will have
  191. no idea what the program is waiting for.) We shall call a system-dependent
  192. subroutine |update_terminal| in order to avoid this problem.
  193.  
  194. @d update_terminal == break(output) {empty the terminal output buffer}
  195.  
  196. @<Glob...@>=
  197. @!buffer:array[0..terminal_line_length] of 0..255;
  198. @!term_in:text_file; {the terminal, considered as an input file}
  199. @y
  200. Since the terminal is being used for both input and output, some systems
  201. need a special routine to make sure that the user can see a prompt message
  202. before waiting for input based on that message. (Otherwise the message
  203. may just be sitting in a hidden buffer somewhere, and the user will have
  204. no idea what the program is waiting for.) We shall call a system-dependent
  205. subroutine |update_terminal| in order to avoid this problem.
  206. @^system dependencies@>
  207.  
  208. @d update_terminal == flush (stdout) {empty the terminal output buffer}
  209. @d term_in == stdin {standard input}
  210.  
  211. @<Glob...@>=
  212. @!buffer:array[0..terminal_line_length] of 0..255;
  213. @z
  214.  
  215. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  216. % [17] Change term_in^, etc.
  217. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  218. @x
  219. @p procedure input_ln; {inputs a line from the terminal}
  220. begin update_terminal; reset(term_in);
  221. if eoln(term_in) then read_ln(term_in);
  222. line_length:=0;
  223. while (line_length<terminal_line_length)and not eoln(term_in) do
  224.   begin buffer[line_length]:=xord[term_in^]; incr(line_length); get(term_in);
  225.   end;
  226. end;
  227. @y
  228. @p procedure input_ln; {inputs a line from the terminal}
  229. begin update_terminal;
  230. if eoln(term_in) then read_ln(term_in);
  231. line_length:=0;
  232. while (line_length<terminal_line_length)and not eoln(term_in) do
  233.   begin buffer[line_length]:=xord[getc(term_in)]; incr(line_length);
  234.   end;
  235. end;
  236. @z
  237.  
  238. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  239. % [47] Open files based on paths.
  240. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  241. @x
  242. @p procedure open_gf_file; {prepares to read packed bytes in |gf_file|}
  243. begin reset(gf_file,name_of_file);
  244. cur_loc:=0;
  245. end;
  246. @#
  247. procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
  248. begin reset(tfm_file,name_of_file);
  249. end;
  250. @y
  251. In C, we use the external |test_read_access| procedure, which also does path
  252. searching based on the user's environment or the default path.  We also
  253. read the command line and print the banner here (since we don't want to
  254. print the banner if the command line is unreasonable).
  255.  
  256. @p procedure open_gf_file; {prepares to read packed bytes in |gf_file|}
  257. begin
  258.    if test_read_access (name_of_file, GF_FILE_PATH)
  259.    then begin
  260.       reset (gf_file, name_of_file);
  261.    end else begin
  262.      print_pascal_string (name_of_file);
  263.      abort (': GF file not found.');
  264.    end;
  265.    cur_loc := 0;
  266. end;
  267. @#
  268. procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
  269. begin
  270.    if test_read_access (name_of_file, TFM_FILE_PATH)
  271.    then begin
  272.       reset (tfm_file, name_of_file);
  273.    end else begin
  274.       print_pascal_string (name_of_file);
  275.       abort (': TFM file not found.');
  276.    end;
  277. end;
  278. @z
  279.  
  280. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  281. % [51] Make get_n_bytes routines work with 16-bit math.
  282. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  283. @x
  284. get_two_bytes:=a*256+b;
  285. @y
  286. get_two_bytes:=a*toint(256)+b;
  287. @z
  288. @x
  289. get_three_bytes:=(a*256+b)*256+c;
  290. @y
  291. get_three_bytes:=(a*toint(256)+b)*256+c;
  292. @z
  293. @x
  294. if a<128 then signed_quad:=((a*256+b)*256+c)*256+d
  295. else signed_quad:=(((a-256)*256+b)*256+c)*256+d;
  296. @y
  297. if a<128 then signed_quad:=((a*toint(256)+b)*256+c)*256+d
  298. else signed_quad:=(((a-256)*toint(256)+b)*256+c)*256+d;
  299. @z
  300.  
  301. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  302. % [52] The memory_word structure is too hard to translate via web2c, so
  303. % we use a hand-coded include file.  Also, b0 (et al.) is used both as a
  304. % field and as a regular variable.  web2c puts field names in the global
  305. % symbol table, so this loses.  Rather than fix web2c (hard), we change
  306. % the name of the field (ugly, but easy).
  307. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  308. @x
  309. @!four_quarters = packed record@;@/
  310.   @!b0:quarterword;
  311.   @!b1:quarterword;
  312.   @!b2:quarterword;
  313.   @!b3:quarterword;
  314.   end;
  315. @!memory_word = record@;@/
  316.   case boolean of
  317.   true: (@!sc:scaled);
  318.   false: (@!qqqq:four_quarters);
  319.   end;
  320. @y
  321. @!four_quarters = packed record@;@/
  322.   @!B0:quarterword;
  323.   @!B1:quarterword;
  324.   @!B2:quarterword;
  325.   @!B3:quarterword;
  326.   end;
  327. @\@/@=#include "gftodmem.h";@>@\ {note the |;| so |web2c| will translate
  328.                                   types that come after this}
  329. @z
  330.  
  331. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  332. % [55] fix references to .b0
  333. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  334. @x
  335. @d char_width_end(#)==#.b0].sc
  336. @d char_width(#)==font_info[width_base[#]+char_width_end
  337. @d char_exists(#)==(#.b0>min_quarterword)
  338. @d char_italic_end(#)==(qo(#.b2)) div 4].sc
  339. @d char_italic(#)==font_info[italic_base[#]+char_italic_end
  340. @d height_depth(#)==qo(#.b1)
  341. @d char_height_end(#)==(#) div 16].sc
  342. @d char_height(#)==font_info[height_base[#]+char_height_end
  343. @d char_depth_end(#)==# mod 16].sc
  344. @d char_depth(#)==font_info[depth_base[#]+char_depth_end
  345. @d char_tag(#)==((qo(#.b2)) mod 4)
  346. @d skip_byte(#)==qo(#.b0)
  347. @d next_char(#)==#.b1
  348. @d op_byte(#)==qo(#.b2)
  349. @d rem_byte(#)==#.b3
  350. @y
  351. @d char_width_end(#)==#.B0].sc
  352. @d char_width(#)==font_info[width_base[#]+char_width_end
  353. @d char_exists(#)==(#.B0>min_quarterword)
  354. @d char_italic_end(#)==(qo(#.B2)) div 4].sc
  355. @d char_italic(#)==font_info[italic_base[#]+char_italic_end
  356. @d height_depth(#)==qo(#.B1)
  357. @d char_height_end(#)==(#) div 16].sc
  358. @d char_height(#)==font_info[height_base[#]+char_height_end
  359. @d char_depth_end(#)==# mod 16].sc
  360. @d char_depth(#)==font_info[depth_base[#]+char_depth_end
  361. @d char_tag(#)==((qo(#.B2)) mod 4)
  362. @d skip_byte(#)==qo(#.B0)
  363. @d next_char(#)==#.B1
  364. @d op_byte(#)==qo(#.B2)
  365. @d rem_byte(#)==#.B3
  366. @z
  367.  
  368. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  369. % [60] Fix 16-bit arithmetic bugs in TFM calculations.
  370. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  371. @x
  372. @ @d read_two_halves_end(#)==#:=b2*256+b3
  373. @d read_two_halves(#)==read_tfm_word; #:=b0*256+b1; read_two_halves_end
  374. @y
  375. @ @d read_two_halves_end(#)==#:=b2*toint(256)+b3
  376. @d read_two_halves(#)==read_tfm_word; #:=b0*toint(256)+b1; read_two_halves_end
  377. @z
  378.  
  379. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  380. % [62] More .b?'s.
  381. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  382. @x
  383.   qw.b0:=qi(b0); qw.b1:=qi(b1); qw.b2:=qi(b2); qw.b3:=qi(b3);
  384. @y
  385.   qw.B0:=qi(b0); qw.B1:=qi(b1); qw.B2:=qi(b2); qw.B3:=qi(b3);
  386. @z
  387.  
  388. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  389. % [62] More arithmetic fixes.
  390. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  391. @x
  392. z:=((b0*256+b1)*256+b2)*16+(b3 div 16);
  393. @y
  394. z:=((b0*toint(256)+b1)*toint(256)+b2)*16+(b3 div 16);
  395. @z
  396. @x
  397.       else if 256*(b2-128)+b3>=nk then abend;
  398. @y
  399.       else if toint(256)*(b2-128)+b3>=nk then abend;
  400. @z
  401.  
  402. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  403. % [78] Change default extension to `.2602gf'.
  404. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  405. @x
  406. l:=3; init_str3(".")("g")("f")(gf_ext);@/
  407. @y
  408. l:=7; init_str7(".")("2")("6")("0")("2")("g")("f")(gf_ext);@/
  409. @z
  410.  
  411. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  412. % [88] Change home_font_area to null_string.
  413. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  414. @x
  415. @ Font metric files whose areas are not given
  416. explicitly are assumed to appear in a standard system area called
  417. |home_font_area|.  This system area name will, of course, vary from place
  418. to place. The program here sets it to `\.{TeXfonts:}'.
  419. @^system dependencies@>
  420. @.TeXfonts@>
  421.  
  422. @<Initialize the strings@>=
  423. l:=9; init_str9("T")("e")("X")("f")("o")("n")("t")("s")(":")(home_font_area);@/
  424. @y
  425. @ Font metric files whose areas are not given
  426. explicitly are assumed to appear in a standard system area called
  427. |home_font_area|.  This system area name will, of course, vary from place
  428. to place. In the {\mc UNIX} version, we set |home_font_area|
  429. to |null_string| because the default areas to search for \.{TFM} files
  430. are built into the routine |test_read_access|.
  431. @^system dependencies@>
  432.  
  433. @<Initialize the strings@>=
  434. l:=0; init_str0(home_font_area);@/
  435. @z
  436.  
  437. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  438. % [90] Change more_name to understand UNIX file name syntax.
  439. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  440. @x
  441. else  begin if (c=">")or(c=":") then
  442.     begin area_delimiter:=pool_ptr; ext_delimiter:=0;
  443.     end
  444.   else if (c=".")and(ext_delimiter=0) then ext_delimiter:=pool_ptr;
  445. @y
  446. else  begin if (c="/") then
  447.     begin area_delimiter:=pool_ptr; ext_delimiter:=0;
  448.     end
  449.   else if c="." then ext_delimiter:=pool_ptr;
  450. @z
  451.  
  452. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  453. % [94] Change start_gf to get file name from the command line.
  454. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  455. @x
  456. @ The |start_gf| procedure prompts the user for the name of the generic
  457. font file to be input. It opens the file, making sure that some input is
  458. present; then it opens the output file.
  459.  
  460. Although this routine is system-independent, it should probably be
  461. modified to take the file name from the command line (without an initial
  462. prompt), on systems that permit such things.
  463.  
  464. @p procedure start_gf;
  465. label found,done;
  466. begin loop@+begin print_nl('GF file name: '); input_ln;
  467. @.GF file name@>
  468.   buf_ptr:=0; buffer[line_length]:="?";
  469.   while buffer[buf_ptr]=" " do incr(buf_ptr);
  470.   if buf_ptr<line_length then
  471.     begin @<Scan the file name in the buffer@>;
  472.     if cur_ext=null_string then cur_ext:=gf_ext;
  473.     pack_file_name(cur_name,cur_area,cur_ext); open_gf_file;
  474.     if not eof(gf_file) then goto found;
  475.     print_nl('Oops... I can''t find file '); print(name_of_file);
  476. @.Oops...@>
  477. @.I can't find...@>
  478.     end;
  479.   end;
  480. found:job_name:=cur_name; pack_file_name(job_name,null_string,dvi_ext);
  481. open_dvi_file;
  482. end;
  483. @y
  484. @ The |start_gf| procedure obtains the name of the generic font file to
  485. be input from the command line.  It opens the file, making sure that
  486. some input is present; then it opens the output file.
  487.  
  488. @p procedure start_gf;
  489. label done;
  490. var arg_buffer: packed array [1..PATH_MAX] of char;
  491.     arg_buf_ptr: 1..PATH_MAX;
  492. begin
  493.   if optind = argc
  494.   then begin
  495.     print ('GF file name: ');
  496.     input_ln;
  497. @.GF file name:@>
  498.   end else begin
  499.     argv (optind, arg_buffer);
  500.     arg_buffer[PATH_MAX] := ' ';
  501.     arg_buf_ptr := 1;
  502.     line_length := 0;
  503.     while (arg_buf_ptr < PATH_MAX)
  504.           and (arg_buffer[arg_buf_ptr] = ' ')
  505.       do incr(arg_buf_ptr);
  506.  
  507.     while (arg_buf_ptr < PATH_MAX)
  508.           and (line_length < terminal_line_length)
  509.           and (arg_buffer[arg_buf_ptr] <> ' ')
  510.     do begin
  511.       buffer[line_length] := xord[arg_buffer[arg_buf_ptr]];
  512.       incr(line_length);
  513.       incr(arg_buf_ptr);
  514.     end;
  515.   end;
  516.  
  517.   buf_ptr:=0; buffer[line_length]:="?";
  518.   while buffer[buf_ptr]=" " do incr(buf_ptr);
  519.   if buf_ptr < line_length
  520.   then begin
  521.     @<Scan the file name in the buffer@>;
  522.     if cur_ext = null_string then cur_ext:=gf_ext;
  523.     pack_file_name (cur_name, cur_area, cur_ext);
  524.     open_gf_file;
  525.   end;
  526.   job_name := cur_name;
  527.   pack_file_name(job_name, null_string, dvi_ext);
  528.   open_dvi_file;
  529. end;
  530. @z
  531.  
  532. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  533. % [107] `write_dvi' is now an external C routine.
  534. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  535. @x
  536. @p procedure write_dvi(@!a,@!b:dvi_index);
  537. var k:dvi_index;
  538. begin for k:=a to b do write(dvi_file,dvi_buf[k]);
  539. end;
  540. @y
  541. In C, we can write out the entire array with one call.
  542. @p procedure write_dvi(@!a,@!b:dvi_index);
  543. begin 
  544.   write_chunk (dvi_file, dvi_buf, a, b);
  545. end;
  546. @z
  547.  
  548. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  549. % [111] More .b?'s.
  550. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  551. @x
  552. dvi_out(qo(font_check[f].b0));
  553. dvi_out(qo(font_check[f].b1));
  554. dvi_out(qo(font_check[f].b2));
  555. dvi_out(qo(font_check[f].b3));@/
  556. @y
  557. dvi_out(qo(font_check[f].B0));
  558. dvi_out(qo(font_check[f].B1));
  559. dvi_out(qo(font_check[f].B2));
  560. dvi_out(qo(font_check[f].B3));@/
  561. @z
  562.  
  563. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  564. % [115] Don't go to final_end, just exit; this is the normal exit from
  565. % the program, so we want to end with a newline if we are being verbose.
  566. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  567. @x
  568. goto final_end;
  569. @y
  570. if verbose then print_ln (' ');
  571. uexit (0);
  572. @z
  573.  
  574. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  575. % [118] And still more .b?'s.
  576. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  577. @x
  578. dummy_info.b0:=qi(0); dummy_info.b1:=qi(0); dummy_info.b2:=qi(0);
  579. dummy_info.b3:=qi(0);
  580. @y
  581. dummy_info.B0:=qi(0); dummy_info.B1:=qi(0); dummy_info.B2:=qi(0);
  582. dummy_info.B3:=qi(0);
  583. @z
  584.  
  585. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  586. % [138] write_ln formatting.
  587. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  588. @x
  589.   begin print_nl('Sorry, I can''t make diagonal rules of slant ',r:10:5,'!');
  590. @y
  591.   begin print_nl('Sorry, I can''t make diagonal rules of slant ');
  592.         print_real(r,10,5); print('!');
  593. @z
  594.  
  595. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  596. % [164] No progress report unless verbose.
  597. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
  598. @x
  599. print('[',total_pages:1); update_terminal; {print a progress report}
  600. @y
  601. if verbose
  602. then begin
  603.   print('[',total_pages:1);
  604.   update_terminal; {print a progress report}
  605. end;
  606. @z
  607.  
  608. @x
  609. print(']'); update_terminal;
  610. @y
  611. if verbose
  612. then begin
  613.   print(']');
  614.   if total_pages mod 13 = 0
  615.   then print_ln (' ')
  616.   else print (' ');
  617.   update_terminal;
  618. end;
  619. @z
  620.  
  621. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  622. % [170] Change offset for overflow labels.  The defaults adds about 2.1
  623. % inches to the right edge of the diagram, which puts it off the paper
  624. % for even moderately large fonts.  Instead, we make it a command-line
  625. % option.
  626. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  627. @x
  628. over_col:=over_col+delta_x+10000000;
  629. @y
  630. over_col := over_col + delta_x + overflow_label_offset;
  631. @z
  632.  
  633. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  634. % [215] Some broken compilers cannot handle 165 labels for the same
  635. % branch of a switch.
  636. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  637. @x
  638. @<Read and process...@>=
  639. loop  @+begin continue: case cur_gf of
  640.   sixty_four_cases(0): k:=cur_gf;
  641.   paint1:k:=get_byte;
  642.   paint2:k:=get_two_bytes;
  643.   paint3:k:=get_three_bytes;
  644.   eoc:goto done1;
  645.   skip0:end_with(blank_rows:=0; do_skip);
  646.   skip1:end_with(blank_rows:=get_byte; do_skip);
  647.   skip2:end_with(blank_rows:=get_two_bytes; do_skip);
  648.   skip3:end_with(blank_rows:=get_three_bytes; do_skip);
  649.   sixty_four_cases(new_row_0),sixty_four_cases(new_row_0+64),
  650.    thirty_two_cases(new_row_0+128),five_cases(new_row_0+160):
  651.     end_with(z:=cur_gf-new_row_0;paint_black:=true);
  652.   xxx1,xxx2,xxx3,xxx4,yyy,no_op:begin skip_nop; goto continue;
  653.     end;
  654.   othercases bad_gf('Improper opcode')
  655.   endcases;@/
  656. @y
  657. @<Read and process...@>=
  658. loop  @+begin continue:
  659.  if (cur_gf>=new_row_0)and(cur_gf<=new_row_0+164) then
  660.     end_with(z:=cur_gf-new_row_0;paint_black:=true)
  661.  else case cur_gf of
  662.   sixty_four_cases(0): k:=cur_gf;
  663.   paint1:k:=get_byte;
  664.   paint2:k:=get_two_bytes;
  665.   paint3:k:=get_three_bytes;
  666.   eoc:goto done1;
  667.   skip0:end_with(blank_rows:=0; do_skip);
  668.   skip1:end_with(blank_rows:=get_byte; do_skip);
  669.   skip2:end_with(blank_rows:=get_two_bytes; do_skip);
  670.   skip3:end_with(blank_rows:=get_three_bytes; do_skip);
  671.   xxx1,xxx2,xxx3,xxx4,yyy,no_op:begin skip_nop; goto continue;
  672.     end;
  673.   othercases bad_gf('Improper opcode')
  674.   endcases;@/
  675. @z
  676.  
  677. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  678. % [219] Call `setpaths'.
  679. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  680. @x
  681. start_gf; {open the input and output files}
  682. @y
  683. {initialize paths from environment variables}
  684. set_paths (GF_FILE_PATH_BIT + TFM_FILE_PATH_BIT);
  685. start_gf; {open the input and output files}
  686. @z
  687.  
  688. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  689. % [still 219] If verbose, output a newline at the end.
  690. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  691. @x
  692. final_end:end.
  693. @y
  694.   if verbose and (total_pages mod 13 <> 0) then print_ln (' ');
  695. end.
  696. @z
  697.  
  698. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  699. % [222] System-dependent changes.
  700. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  701. @x
  702. @* System-dependent changes.
  703. This section should be replaced, if necessary, by changes to the program
  704. that are necessary to make \.{GFtoDVI} work at a particular installation.
  705. It is usually best to design your change file so that all changes to
  706. previous sections preserve the section numbering; then everybody's version
  707. will be consistent with the printed program. More extensive changes,
  708. which introduce new sections, can be inserted here; then only the index
  709. itself will get a new section number.
  710. @^system dependencies@>
  711. @y
  712. @* System-dependent changes.  We want to parse a Unix-style command
  713. line.
  714.  
  715. This macro tests if its argument is the current option, as represented
  716. by the index variable |option_index|.
  717.  
  718. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0)
  719.  
  720. @<Parse arguments@> =
  721. begin
  722.   @<Define the option table@>;
  723.   repeat
  724.     getopt_return_val := getopt_long_only (argc, gargv, '', long_options,
  725.                                            address_of_int (option_index));
  726.     if getopt_return_val <> -1
  727.     then begin
  728.       if getopt_return_val = "?"
  729.       then uexit (1); {|getopt| has already given an error message.}
  730.       
  731.       if argument_is ('overflow-label-offset')
  732.       then begin
  733.         offset_in_points := atof (optarg);
  734.         overflow_label_offset := round (offset_in_points * 65536);
  735.       end
  736.       
  737.       else
  738.         {It was just a flag; |getopt| has already done the assignment.}
  739.         do_nothing;
  740.     end;
  741.   until getopt_return_val = -1;
  742.  
  743.   {Now |optind| is the index of first non-option on the command line.}
  744. end
  745.  
  746.  
  747. @ The array of information we pass in.  The type |getopt_struct| is
  748. defined in C, to avoid type clashes.  We also need to know the return
  749. value from getopt, and the index of the current option.
  750.  
  751. @<Local var...@> =
  752. @!long_options: array[0..n_options] of getopt_struct;
  753. @!getopt_return_val: integer;
  754. @!option_index: c_int_type;
  755. @!current_option: 0..n_options;
  756.  
  757. @ Here are the options we allow.  The first is just a switch that
  758. determines whether or not we print status information.
  759. @.-verbose@>
  760.  
  761. @<Define the option...@> =
  762. current_option := 0;
  763. long_options[0].name := 'verbose';
  764. long_options[0].has_arg := 0;
  765. long_options[0].flag := address_of_int (verbose);
  766. long_options[0].val := 1;
  767. incr (current_option);
  768.  
  769. @ Here is the variable to go with the switch.
  770.  
  771. @<Glob...@> =
  772. @!verbose: c_int_type;
  773.  
  774. @ |verbose| starts off |false|.
  775.  
  776. @<Initialize the option...@> =
  777. verbose := false;
  778.  
  779. @ The second option determines how far from the right edge of the
  780. character boxes we print overflow labels.
  781. @.-overflow-label-offset@>
  782.  
  783. @<Define the option...@> =
  784. long_options[current_option].name := 'overflow-label-offset';
  785. long_options[current_option].has_arg := 1;
  786. long_options[current_option].flag := 0;
  787. long_options[current_option].val := 0;
  788. incr (current_option);
  789.  
  790. @ It's easier on the user to specify the value in \TeX\ points, but we
  791. want to store it in scaled points.
  792.  
  793. @<Glob...@> =
  794. @!overflow_label_offset: integer; {in scaled points}
  795. @!offset_in_points: real;
  796.  
  797. @ The default offset is ten million scaled points---a little more than
  798. two inches.
  799.  
  800. @<Initialize the option...@> =
  801. overflow_label_offset := 10000000;
  802.  
  803. @ An element with all zeros always ends the list.
  804.  
  805. @<Define the option...@> =
  806. long_options[current_option].name := 0;
  807. long_options[current_option].has_arg := 0;
  808. long_options[current_option].flag := 0;
  809. long_options[current_option].val := 0;
  810.  
  811. @ Pascal compilers won't count the number of elements in an array
  812. constant for us.  This doesn't include the zero-element at the end,
  813. because this array starts at index zero.
  814.  
  815. @<Constants...@> =
  816. n_options = 2;
  817. arg_options = 1;
  818. @z
  819.