001078: Arrange things so that listings of METAFONT only show changed modules. @x % Here is TeX material that gets inserted after \input webmac @y % Here is TeX material that gets inserted after \input webmac \let\maybe=\iffalse @z 006554: Change the banner line. @x @d banner=='This is METAFONT, Version 0.9999' {printed when \MF\ starts} @y @d banner=='This is METAFONT 0.9999, for Cedar 6.0' {printed when \MF\ starts} @z 009530: Define macros for read_ln and write_ln that expand without the underscores. @x @f type==true {but `|type|' will not be treated as a reserved word} @y @f type==true {but `|type|' will not be treated as a reserved word} @d write_ln==writeln {since our Tangle doesn't strip out "\_"} @d read_ln==readln @z 009833: Add external procedure declarations for things implemented in Cedar @x procedure initialize; {this procedure gets things started properly} @y @@/ procedure initialize; {this procedure gets things started properly} @z 011873: Turn on debugging code. @x @d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging} @d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging} @y @d debug== @d gubed== @z 012050: Turn on statistics code. @x @d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering usage statistics} @d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering usage statistics} @y @d stat== @d tats== @z 015529: (~TRAP) Set mem_max to 50000. @x @!mem_max=30000; {greatest index in \MF's internal |mem| array; @y @!mem_max=50000; {greatest index in \MF's internal |mem| array; @z 015764: (~TRAP) Up the buf_size, so that long input lines don't cause errors. @x @!buf_size=500; {maximum number of characters simultaneously present in @y @!buf_size=7500; {maximum number of characters simultaneously present in @z 015899: (~TRAP) Set error_line and half_error_line small, but max_print_line very large. @x @!error_line=72; {width of context lines on terminal error messages} @!half_error_line=42; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=79; {width of longest text lines output; should be at least 60} @y @!error_line=64; {width of context lines on terminal error messages} @!half_error_line=32; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=30000; {width of longest text lines output; should be at least 60} @z 016177: (~TRAP) Change screen_width and screen_depth to match Viewers setup @x @!screen_width=768; {number of pixels in each row of screen display} @!screen_depth=1024; {number of pixels in each column of screen display} @y @!screen_width=1000; {number of pixels in each row of screen display} @!screen_depth=700; {number of pixels in each column of screen display} @z 017084: Up the file_name_size to 127, enough for FS including version numbers. @x @!file_name_size=40; {file names shouldn't be longer than this} @y @!file_name_size=127; {file names shouldn't be longer than this} @z 017148: Delete pool name, since that initialization will be done by an external proc. @x @!pool_name='MFbases:MF.POOL '; {string of length |file_name_size|; tells where the string pool appears} @.MFbases@> @y @z 018315: (~TRAP) Set mem_top to 50000. @x @d mem_top==30000 {largest index in the |mem| array dumped by \.{INIMF}; must be substantially larger than |mem_min| and not greater than |mem_max|} @y @d mem_top==50000 {largest index in the |mem| array dumped by \.{INIMF}; must be substantially larger than |mem_min| and not greater than |mem_max|} @z 024575: Allow for eight-bit characters @x @d last_text_char=127 {ordinal number of the largest element of |text_char|} @y @d last_text_char=255 {ordinal number of the largest element of |text_char|} @z 028547: Set up the character-code mapping to be the identity for now. @x for i:=1 to @'37 do xchr[i]:=' '; @y for i:=1 to @'37 do xchr[i]:=chr(i); @z 033425: Replace Pascal-H extended file routines with external calls. @x @d reset_OK(#)==erstat(#)=0 @d rewrite_OK(#)==erstat(#)=0 @p function a_open_in(var @!f:alpha_file):boolean; {open a text file for input} begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f); end; @# function a_open_out(var @!f:alpha_file):boolean; {open a text file for output} begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f); end; @# function b_open_out(var @!f:byte_file):boolean; {open a binary file for output} begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f); end; @# function w_open_in(var @!f:word_file):boolean; {open a word file for input} begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f); end; @# function w_open_out(var @!f:word_file):boolean; {open a word file for output} begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f); end; @y @p function a_open_in(var f:alpha_file):boolean; external; {open a text file for input} @# function a_open_out(var f:alpha_file):boolean; external; {open a text file for output} @# function b_open_in(var f:byte_file):boolean; external; {open a binary file for input} @# function b_open_out(var f:byte_file):boolean; external; {open a binary file for output} @# function w_open_in(var f:word_file):boolean; external; {open a word file for input} @# function w_open_out(var f:word_file):boolean; external; {open a word file for output} @z 034593: Also make close-operations external. @x @p procedure a_close(var @!f:alpha_file); {close a text file} begin close(f); end; @# procedure b_close(var @!f:byte_file); {close a binary file} begin close(f); end; @# procedure w_close(var @!f:word_file); {close a word file} begin close(f); end; @y @p procedure a_close(var @!f:alpha_file); external; {close a text file} @# procedure b_close(var @!f:byte_file); external; {close a binary file} @# procedure w_close(var @!f:word_file); external; {close a word file} @z 039158: Terminal files are also external. @x @d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input} @d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output} @y @d t_open_in==reset_term_in(term_in) {open the terminal for text input} @d t_open_out==rewrite_term_out(term_out) {open the terminal for text output} @z 040142: Remove break_in from clear_terminal @x @d clear_terminal == break_in(term_in,true) {clear the terminal input buffer} @y @d clear_terminal == {clear the terminal input buffer} @z 043002: Read the tail of the command line as the first line of input @x begin t_open_in; @y const cmd_blank = 0; cmd_ok = 1; cmd_overflow = -1; var cmd_status:integer; begin t_open_in; cmd_status:=stuff_on_cmd_line; if cmd_status=cmd_overflow then overflow("buffer size",buf_size); if cmd_status=cmd_ok then begin init_terminal:=true; return end; @z 054491: Set up pool_name properly, filling out with blanks. @x name_of_file:=pool_name; {we needn't set |name_length|} @y set_pool_name; @z 072347: Set process priority back up to normal for error handling interactions. @x if interaction=error_stop_mode then @; @y if interaction=error_stop_mode then begin set_normal_priority; @; end; @z 072646: But set it back down to background when the interaction is over. @x exit:end; @y exit: set_background_priority; end; @z 073758: (~TRAP) In Cedar, character counts are more useful than line numbers. My basic plan is to store character counts of the beginning of the lines in Knuth's "line" variables. To avoid confusion with zero, which Knuth uses as a special flag, I shall actually store (charPos+1) instead. This works out wonderfully, since the Position button in Tioga starts counting characters from one instead of from zero anyway. @x print(" at line "); print_int(line); @y print(" near character "); print_int(line); @z 123633: Make life easy on the compiler, given that min_halfword=min_quarterword=0. @x @d ho(#)==#-min_halfword {to take a sixteen-bit item from a halfword} @d qo(#)==#-min_quarterword {to read eight bits from a quarterword} @d qi(#)==#+min_quarterword {to store eight bits in a quarterword} @y @d ho(#)==# {to take a sixteen-bit item from a halfword} @d qo(#)==# {to read eight bits from a quarterword} @d qi(#)==# {to store eight bits in a quarterword} @z 124117: Change tag fields in variant records to enumerated types. @x @!two_choices = 1..2; {used when there are two variants in a record} @!three_choices = 1..3; {used when there are three variants in a record} @!two_halves = packed record@;@/ @!rh:halfword; case two_choices of 1: (@!lh:halfword); 2: (@!b0:quarterword; @!b1:quarterword); end; @!four_quarters = packed record@;@/ @!b0:quarterword; @!b1:quarterword; @!b2:quarterword; @!b3:quarterword; end; @!memory_word = record@;@/ case three_choices of 1: (@!int:integer); 2: (@!hh:two_halves); 3: (@!qqqq:four_quarters); end; @y @!two_choices = (c1of2, c2of2); {used when there are two variants in a record} @!three_choices = (c1of3, c2of3, c3of3); {used when there are three variants in a record} @!two_halves = packed record@;@/ @!rh:halfword; case two_choices of c1of2: (@!lh:halfword); c2of2: (@!b0:quarterword; @!b1:quarterword); end; @!four_quarters = packed record@;@/ @!b0:quarterword; @!b1:quarterword; @!b2:quarterword; @!b3:quarterword; end; @!memory_word = record@;@/ case three_choices of c1of3: (@!int:integer); c2of3: (@!hh:two_halves); c3of3: (@!qqqq:four_quarters); end; @z 170045: Fix up fix_date_and_time @x begin internal[time]:=12*60*unity; {minutes since midnight} internal[day]:=4*unity; {fourth day of the month} internal[month]:=7*unity; {seventh month of the year} internal[year]:=1776*unity; {Anno Domini} end; @y var the_time, the_day, the_month, the_year:integer; begin read_the_clock(the_time, the_day, the_month, the_year); internal[time]:=the_time*unity; {minutes since midnight} internal[day]:=the_day*unity; {day of the month} internal[month]:=the_month*unity; {month of the year} internal[year]:=the_year*unity; {Anno Domini} end; @z 171419: (~TRAP) Change "line" to "character" in error message. @x print(" at line "); print_int(line); @y print(" near character "); print_int(line); @z 173750: Make tabs and form feed characters legal space characters. @x char_class[127]:=invalid_class; @y char_class[127]:=invalid_class; char_class[9]:=space_class; char_class[12]:=space_class; @z 245041: (BUG) Remove unused variable r @x @!r,@!s,@!t:pointer; {registers for list traversal} @y @!s,@!t:pointer; {registers for list traversal} @z 249628: (BUG) Remove unused variables sine and cosine @x procedure solve_choices(@!p,@!q:pointer;@!n:halfword); label found,exit; var @!k:0..path_size; {current knot number} @!r,@!s,@!t:pointer; {registers for list traversal} @!sine,@!cosine:fraction; {trig functions of various angles} @y procedure solve_choices(@!p,@!q:pointer;@!n:halfword); label found,exit; var @!k:0..path_size; {current knot number} @!r,@!s,@!t:pointer; {registers for list traversal} @z 347291: Break up procedure make_spec, using a nested procedure. @x @@; begin cur_spec:=h; if tracing>0 then print_path(cur_spec,", before subdivision into octants",true); max_allowed:=fraction_one-half_unit-1-safety_margin; @; quadrant_subdivide; {subdivide each cubic into pieces belonging to quadrants} if internal[autorounding]>0 then xy_round; octant_subdivide; {complete the subdivision} if internal[autorounding]>unity then diag_round; @; @; @y @@; procedure m_s_bit; begin @; end; @# begin cur_spec:=h; if tracing>0 then print_path(cur_spec,", before subdivision into octants",true); max_allowed:=fraction_one-half_unit-1-safety_margin; @; quadrant_subdivide; {subdivide each cubic into pieces belonging to quadrants} if internal[autorounding]>0 then xy_round; octant_subdivide; {complete the subdivision} if internal[autorounding]>unity then diag_round; @; m_s_bit; @z 351986: Break up the procedure quadrant_subdivide using a nested procedure. The Cedar compiler is running out of space in a per-procedure data structure, so this will suffice. @x procedure quadrant_subdivide; label continue,exit; var @!p,@!q,@!r,@!s,@!pp,@!qq:pointer; {for traversing the lists} @!first_x,@!first_y:scaled; {unnegated coordinates of node |cur_spec|} @!del1,@!del2,@!del3,@!del,@!dmax:scaled; {proportional to the control points of a quadratic derived from a cubic} @!t:fraction; {where a quadratic crosses zero} @!dest_x,@!dest_y:scaled; {final values of |x| and |y| in the current cubic} @!constant_x:boolean; {is |x| constant between |p| and |q|?} begin p:=cur_spec; first_x:=x_coord(cur_spec); first_y:=y_coord(cur_spec); repeat continue: q:=link(p); @; @; p:=q; until p=cur_spec; exit:end; @y procedure quadrant_subdivide; label continue,exit; var @!p,@!q,@!r,@!s,@!pp,@!qq:pointer; {for traversing the lists} @!first_x,@!first_y:scaled; {unnegated coordinates of node |cur_spec|} @!del1,@!del2,@!del3,@!del,@!dmax:scaled; {proportional to the control points of a quadratic derived from a cubic} @!t:fraction; {where a quadratic crosses zero} @!dest_x,@!dest_y:scaled; {final values of |x| and |y| in the current cubic} @!constant_x:boolean; {is |x| constant between |p| and |q|?} @# procedure subdiv1; begin @; end; @# begin p:=cur_spec; first_x:=x_coord(cur_spec); first_y:=y_coord(cur_spec); repeat continue: q:=link(p); subdiv1; @; p:=q; until p=cur_spec; exit:end; @z 378217: Break up procedure diag_round using a nested procedure. @x procedure diag_round; var @!p,@!q,@!pp:pointer; {list manipulation registers} @!b,@!a,@!bb,@!aa,@!d,@!c,@!dd,@!cc:scaled; {before and after values} @!pen_edge:scaled; {offset that governs rounding} @!alpha,@!beta:fraction; {coefficients of linear transformation} @!next_a:scaled; {|after[k]| before it might have changed} @!all_safe:boolean; {does everything look OK so far?} @!k:0..max_wiggle; {runs through before-and-after values} @!first_x,@!first_y:scaled; {coordinates before rounding} begin p:=cur_spec; cur_rounding_ptr:=0; repeat q:=link(p); @; @y procedure diag_round; var @!p,@!q,@!pp:pointer; {list manipulation registers} @!b,@!a,@!bb,@!aa,@!d,@!c,@!dd,@!cc:scaled; {before and after values} @!pen_edge:scaled; {offset that governs rounding} @!alpha,@!beta:fraction; {coefficients of linear transformation} @!next_a:scaled; {|after[k]| before it might have changed} @!all_safe:boolean; {does everything look OK so far?} @!k:0..max_wiggle; {runs through before-and-after values} @!first_x,@!first_y:scaled; {coordinates before rounding} @# procedure inner_diag_round; begin @; end; @# begin p:=cur_spec; cur_rounding_ptr:=0; repeat q:=link(p); inner_diag_round; @z 431357: Break up procedure fill_envelope using a nested procedure. @x @@; begin if internal[tracing_edges]>0 then begin_edge_tracing; p:=spec_head; {we assume that |left_type(spec_head)=endpoint|} repeat octant:=left_octant(p); h:=cur_pen+octant; @; @; @y @@; @# procedure inner_fill; begin @; end; @# begin if internal[tracing_edges]>0 then begin_edge_tracing; p:=spec_head; {we assume that |left_type(spec_head)=endpoint|} repeat octant:=left_octant(p); h:=cur_pen+octant; @; inner_fill; @z 481976: Break up the procedure cubic_intersection using several nested procedures. @x @p procedure cubic_intersection(@!p,@!pp:pointer); label continue, not_found, exit; var @!q,@!qq:pointer; {|link(p)|, |link(pp)|} begin time_to_go:=max_patience; @; loop@+ begin continue: if delx-tol<=stack_max(x_packet(xy))-stack_min(u_packet(uv)) then if delx+tol>=stack_min(x_packet(xy))-stack_max(u_packet(uv)) then if dely-tol<=stack_max(y_packet(xy))-stack_min(v_packet(uv)) then if dely+tol>=stack_min(y_packet(xy))-stack_max(v_packet(uv)) then begin if cur_t>=two then {we've done 17 bisections} begin cur_t:=half(cur_t+1); cur_tt:=half(cur_tt+1); return; end; @; @y @p procedure inter_subdivide; @ begin c_i_subdiv1; c_i_subdiv2; c_i_subdiv3; c_i_subdiv4; end; @# procedure cubic_intersection(@!p,@!pp:pointer); label continue, not_found, exit; var @!q,@!qq:pointer; {|link(p)|, |link(pp)|} @ begin time_to_go:=max_patience; c_i_init1; c_i_init2; loop@+ begin continue: if delx-tol<=stack_max(x_packet(xy))-stack_min(u_packet(uv)) then if delx+tol>=stack_min(x_packet(xy))-stack_max(u_packet(uv)) then if dely-tol<=stack_max(y_packet(xy))-stack_min(v_packet(uv)) then if dely+tol>=stack_min(y_packet(xy))-stack_max(v_packet(uv)) then begin if cur_t>=two then {we've done 17 bisections} begin cur_t:=half(cur_t+1); cur_tt:=half(cur_tt+1); return; end; inter_subdivide; @z 483422: Here are some of the nested procedures which are part of the break up of cubic_intersection. @x @= q:=link(p); qq:=link(pp); bisect_ptr:=int_packets;@/ u1r:=right_x(p)-x_coord(p); u2r:=left_x(q)-right_x(p); u3r:=x_coord(q)-left_x(q); set_min_max(ur_packet);@/ v1r:=right_y(p)-y_coord(p); v2r:=left_y(q)-right_y(p); v3r:=y_coord(q)-left_y(q); set_min_max(vr_packet);@/ x1r:=right_x(pp)-x_coord(pp); x2r:=left_x(qq)-right_x(pp); x3r:=x_coord(qq)-left_x(qq); set_min_max(xr_packet);@/ y1r:=right_y(pp)-y_coord(pp); y2r:=left_y(qq)-right_y(pp); y3r:=y_coord(qq)-left_y(qq); set_min_max(yr_packet);@/ delx:=x_coord(p)-x_coord(pp); dely:=y_coord(p)-y_coord(pp);@/ tol:=0; uv:=r_packets; xy:=r_packets; three_l:=0; cur_t:=1; cur_tt:=1 @y @= procedure c_i_init1; begin q:=link(p); qq:=link(pp); bisect_ptr:=int_packets;@/ u1r:=right_x(p)-x_coord(p); u2r:=left_x(q)-right_x(p); u3r:=x_coord(q)-left_x(q); set_min_max(ur_packet);@/ v1r:=right_y(p)-y_coord(p); v2r:=left_y(q)-right_y(p); v3r:=y_coord(q)-left_y(q); set_min_max(vr_packet);@/ end; @# procedure c_i_init2; begin x1r:=right_x(pp)-x_coord(pp); x2r:=left_x(qq)-right_x(pp); x3r:=x_coord(qq)-left_x(qq); set_min_max(xr_packet);@/ y1r:=right_y(pp)-y_coord(pp); y2r:=left_y(qq)-right_y(pp); y3r:=y_coord(qq)-left_y(qq); set_min_max(yr_packet);@/ delx:=x_coord(p)-x_coord(pp); dely:=y_coord(p)-y_coord(pp);@/ tol:=0; uv:=r_packets; xy:=r_packets; three_l:=0; cur_t:=1; cur_tt:=1 end; @z 484100: And here are the other nested procedures for cubic_intersection. @x @ @= stack_dx:=delx; stack_dy:=dely; stack_tol:=tol; stack_uv:=uv; stack_xy:=xy; bisect_ptr:=bisect_ptr+int_increment;@/ double(cur_t); double(cur_tt);@/ u1l:=stack_1(u_packet(uv)); u3r:=stack_3(u_packet(uv)); u2l:=half(u1l+stack_2(u_packet(uv))); u2r:=half(u3r+stack_2(u_packet(uv))); u3l:=half(u2l+u2r); u1r:=u3l; set_min_max(ul_packet); set_min_max(ur_packet);@/ v1l:=stack_1(v_packet(uv)); v3r:=stack_3(v_packet(uv)); v2l:=half(v1l+stack_2(v_packet(uv))); v2r:=half(v3r+stack_2(v_packet(uv))); v3l:=half(v2l+v2r); v1r:=v3l; set_min_max(vl_packet); set_min_max(vr_packet);@/ x1l:=stack_1(x_packet(xy)); x3r:=stack_3(x_packet(xy)); x2l:=half(x1l+stack_2(x_packet(xy))); x2r:=half(x3r+stack_2(x_packet(xy))); x3l:=half(x2l+x2r); x1r:=x3l; set_min_max(xl_packet); set_min_max(xr_packet);@/ y1l:=stack_1(y_packet(xy)); y3r:=stack_3(y_packet(xy)); y2l:=half(y1l+stack_2(y_packet(xy))); y2r:=half(y3r+stack_2(y_packet(xy))); y3l:=half(y2l+y2r); y1r:=y3l; set_min_max(yl_packet); set_min_max(yr_packet);@/ uv:=l_packets; xy:=l_packets; double(delx); double(dely);@/ tol:=tol-three_l+tol_step; double(tol); three_l:=three_l+tol_step @y @ @= procedure c_i_subdiv1; begin stack_dx:=delx; stack_dy:=dely; stack_tol:=tol; stack_uv:=uv; stack_xy:=xy; bisect_ptr:=bisect_ptr+int_increment;@/ double(cur_t); double(cur_tt);@/ u1l:=stack_1(u_packet(uv)); u3r:=stack_3(u_packet(uv)); u2l:=half(u1l+stack_2(u_packet(uv))); u2r:=half(u3r+stack_2(u_packet(uv))); u3l:=half(u2l+u2r); u1r:=u3l; set_min_max(ul_packet); set_min_max(ur_packet);@/ end; @# procedure c_i_subdiv2; begin v1l:=stack_1(v_packet(uv)); v3r:=stack_3(v_packet(uv)); v2l:=half(v1l+stack_2(v_packet(uv))); v2r:=half(v3r+stack_2(v_packet(uv))); v3l:=half(v2l+v2r); v1r:=v3l; set_min_max(vl_packet); set_min_max(vr_packet);@/ end; @# procedure c_i_subdiv3; begin x1l:=stack_1(x_packet(xy)); x3r:=stack_3(x_packet(xy)); x2l:=half(x1l+stack_2(x_packet(xy))); x2r:=half(x3r+stack_2(x_packet(xy))); x3l:=half(x2l+x2r); x1r:=x3l; set_min_max(xl_packet); set_min_max(xr_packet);@/ end; @# procedure c_i_subdiv4; begin y1l:=stack_1(y_packet(xy)); y3r:=stack_3(y_packet(xy)); y2l:=half(y1l+stack_2(y_packet(xy))); y2r:=half(y3r+stack_2(y_packet(xy))); y3l:=half(y2l+y2r); y1r:=y3l; set_min_max(yl_packet); set_min_max(yr_packet);@/ uv:=l_packets; xy:=l_packets; double(delx); double(dely);@/ tol:=tol-three_l+tol_step; double(tol); three_l:=three_l+tol_step end; @z 489772: (~TRAP) Replace default definitions of screen functions with external references. @x @p function init_screen:boolean; begin init_screen:=false; end; @# procedure update_screen; {will be called only if |init_screen| returns |true|} begin @!init wlog_ln('Calling UPDATESCREEN');@+tini {for testing only} end; @y @p function init_screen:boolean; external; procedure update_screen; external; @z 491843: (~TRAP) Another screen routine. @x @p procedure blank_rectangle(@!left_col,@!right_col:screen_col; @!top_row,@!bot_row:screen_row); var @!r:screen_row; @!c:screen_col; begin @{@+for r:=top_row to bot_row-1 do for c:=left_col to right_col-1 do screen_pixel[r,c]:=white;@+@}@/ @!init wlog_cr; {this will be done only after |init_screen=true|} wlog_ln('Calling BLANKRECTANGLE(',left_col:1,',', right_col:1,',',top_row:1,',',bot_row:1,')');@+tini end; @y @p procedure blank_rectangle(@!left_col,@!right_col:screen_col; @!top_row,@!bot_row:screen_row); external; @z 491843: (~TRAP) The last screen routine. @x @p procedure paint_row(@!r:screen_row;@!b:pixel_color;var @!a:trans_spec; @!n:screen_col); var @!k:screen_col; {an index into |a|} @!c:screen_col; {an index into |screen_pixel|} begin @{ k:=0; c:=a[0]; repeat incr(k); repeat screen_pixel[r,c]:=b; incr(c); until c=a[k]; b:=black-b; {$|black|\swap|white|$} until k=n;@+@}@/ @!init wlog('Calling PAINTROW(',r:1,',',b:1,';'); {this is done only after |init_screen=true|} for k:=0 to n do begin wlog(a[k]:1); if k<>n then wlog(','); end; wlog_ln(')');@+tini end; @y @p procedure paint_row(@!r:screen_row;@!b:pixel_color;var @!a:trans_spec; @!n:screen_col); external; @z 545312: (~TRAP) Report error locations by character count rather than line number. In this particular case, I adjust the value of line in order to indicate the exact character at which the error happened. @x else begin print_nl("l."); print_int(line); @y else begin print_nl("c."); print_int(line+(loc-start)); @z 554108: (BUG) Remove unused variable s @x @p procedure back_input; {undoes one token of input} var @!p:pointer; {a token list of length one} @!s:0..param_size; {value of |param_start| on the current level} @y @p procedure back_input; {undoes one token of input} var @!p:pointer; {a token list of length one} @z 559523: (~TRAP) Change message from "line" to "character" @x else begin print_err("Incomplete if; all text was ignored after line "); @y else begin print_err("Incomplete if; all text was ignored after character "); @z 563316: Add variable k_plus_one to fix signed/unsigned ambiguity below. @x var @!k:0..buf_size; {an index into |buffer|} @y var @!k:0..buf_size; {an index into |buffer|} @!k_plus_one:halfword; {Fix for a signed/unsigned ambiguity in Cedar} @z 566248: Fix for a signed/unsigned ambiguity in Cedar @x if loc=k+1 then cur_mod:=buffer[k] @y k_plus_one:=k+1; if loc=k_plus_one then cur_mod:=buffer[k] @z 570678: (~TRAP) Set "line" to character count rather than line number. Remember that we want to store (charPos+1) in "line", but the offset of plus one comes for free, since Pascal has read the first character of the new line behind our backs. @x begin incr(line); first:=start; @y begin line:=file_get_pos(cur_file); first:=start; @z 623469: Default file directory @x @d MF_area=="MFinputs:" @.MFinputs@> @y @= @!MF_area:str_number; @.MFinputs@> @z 623821: Adjust parsing of file names. @x else begin if (c=">")or(c=":") then begin area_delimiter:=pool_ptr; ext_delimiter:=0; end else if (c=".")and(ext_delimiter=0) then ext_delimiter:=pool_ptr; @y else begin if (c=">")or(c="/")or(c="]") then area_delimiter:=pool_ptr else if (c=".") then ext_delimiter:=pool_ptr; @z 625985: We shall generate base file names in Cedar, working from the default name in the user profile. Hence, we here replace three modules by dummies (to keep the numbering the same). @x @ A messier routine is also needed, since base file names must be scanned before \MF's string mechanism has been initialized. We shall use the global variable |MF_base_default| to supply the text for default system areas and extensions related to base files. @^system dependencies@> @d base_default_length=18 {length of the |MF_base_default| string} @d base_area_length=8 {length of its area part} @d base_ext_length=5 {length of its `\.{.base}' part} @= @!MF_base_default:packed array[1..base_default_length] of char; @ @= MF_base_default:='MFbases:plain.base'; @.MFbases@> @.plain@> @^system dependencies@> @ @= if base_default_length>file_name_size then bad:=41; @y @ This module is a dummy. The default name of the base file is dealt with directly in Cedar. @ So is this one. @ This one too. @z 627224: Pack_buffered_name in Pascal is replaced by three external relatives. @x @p procedure pack_buffered_name(@!n:small_number;@!a,@!b:integer); var @!k:integer; {number of positions filled in |name_of_file|} @!c: ASCII_code; {character being packed} @!j:integer; {index into |buffer| or |MF_base_default|} begin if n+b-a+1+base_ext_length>file_name_size then b:=a+file_name_size-n-1-base_ext_length; k:=0; for j:=1 to n do append_to_name(xord[MF_base_default[j]]); for j:=a to b do append_to_name(buffer[j]); for j:=base_default_length-base_ext_length+1 to base_default_length do append_to_name(xord[MF_base_default[j]]); if k<=file_name_size then name_length:=k@+else name_length:=file_name_size; for k:=name_length+1 to file_name_size do name_of_file[k]:=' '; end; @y Actually, in Cedar, we replace |pack_buffered_name| in Pascal by three external relatives. @p procedure pack_buffered_name(@!a,@!b:integer); external; procedure pack_default_area(@!a,@!b:integer); external; procedure pack_all_default; external; @z 628600: Change first call on pack_buffered_name to a call on an external. @x pack_buffered_name(0,loc,j-1); {try first without the system file area} @y pack_buffered_name(loc,j-1); {try first without the system file area} @z 628717: Change second call on pack_buffered_name to a call on an external. @x pack_buffered_name(base_area_length,loc,j-1); @y pack_default_area(loc,j-1); @z 628868: Change message to indicate that PLAIN isn't necessarily the default base file. @x wterm_ln('Sorry, I can''t find that base;',' will try PLAIN.'); @y wterm_ln('Sorry, I can''t find that base;',' will try your default.'); @z 629053: Change third call on pack_buffered_name to a call on an external. @x pack_buffered_name(base_default_length-base_ext_length,1,0); @y pack_all_default; @z 629173: Change another message to indicate that PLAIN isn't necessarily the default base file. @x wterm_ln('I can''t find the PLAIN base file!'); @y wterm_ln('I can''t find your default base file!'); @z 630161: Report full names of open files by calls to system dependent externals. @x function a_make_name_string(var @!f:alpha_file):str_number; begin a_make_name_string:=make_name_string; end; function b_make_name_string(var @!f:byte_file):str_number; begin b_make_name_string:=make_name_string; end; function w_make_name_string(var @!f:word_file):str_number; begin w_make_name_string:=make_name_string; end; @y function a_make_name_string(var @!f:alpha_file):str_number; external; function b_make_name_string(var @!f:byte_file):str_number; external; function w_make_name_string(var @!f:word_file):str_number; external; @z 637118: Add variable to fix another signed/unsigned ambiguity. @x @p procedure start_input; {\MF\ will \.{input} something} label done; @y @p procedure start_input; {\MF\ will \.{input} something} label done; var str_ptr_minus_one : halfword; @z 638038: Make the signed/unsigned ambiguity fix. @x if name=str_ptr-1 then {we can conserve string pool space now} @y str_ptr_minus_one:=str_ptr-1; if name=str_ptr_minus_one then {we can conserve string pool space now} @z 638481: No change here, since it happens that 1 is correct value of (charPos+1) at the start of a file. @x buffer[limit]:="%"; first:=limit+1; loc:=start; line:=1; @y buffer[limit]:="%"; first:=limit+1; loc:=start; line:=1; @z 667356: (~TRAP) Change "line" to "character" in yet another error message. @x begin print_err("A group begun on line "); @y begin print_err("A group begun near character "); @z 684330: (BUG) Variables q and r are not used. @x procedure scan_secondary; label restart,continue; var @!p,@!q,@!r:pointer; {for list manipulation} @y procedure scan_secondary; label restart,continue; var @!p:pointer; {for list manipulation} @z 794464: (BUG) Variable t is not used. @x procedure do_add_to; label done, not_found; var @!lhs,@!rhs:pointer; {variable on left, path on right} @!t:small_number; {variant of |with_option|} @y procedure do_add_to; label done, not_found; var @!lhs,@!rhs:pointer; {variable on left, path on right} @z 887525: Replace ready_already by the new boolean start_like_inimf. @x should also be provided for commonly used bases. @:METAFONTbook}{\sl The {\logos METAFONT\/}book@> @.cmbase@> @.plain@> @= @!ready_already:integer; {a sacrifice of purity for economy} @y should also be provided for commonly used bases. @:METAFONTbook}{\sl The {\logos METAFONT\/}book@> @.cmbase@> @.plain@> In Cedar, we can't do any preloading, more's the pity, but we can and must combine the two versions of \MF\ (\.{INIMF} and \.{VIRMF}) into a single program. To do so, we add this new |boolean| variable. @= @!start_like_inimf:boolean; {otherwise, we start up like \MF} @z 887934: Wrap up the main code into a procedure body. @x @p begin @!{|start_here|} @y In Cedar, we must encapsulate the main program in a procedure so that we can fit it into a module. @p procedure the_real_mf; begin @!{|start_here|} @z 888070: Delete test on ready_already; instead, set process priority down to background. @x if ready_already=314159 then goto start_of_MF; @y set_background_priority; @z 888369: Only intialize tables, strings and primitives if we are to start_like_inimf; else, reading the format will take care of these initializations. @x @!init if not get_strings_started then goto final_end; init_tab; {initialize the tables} init_prim; {call |primitive| for each primitive} tini@/ @y if start_like_inimf then begin if not get_strings_started then goto final_end; init_tab; {initialize the tables} init_prim; {call |primitive| for each primitive} end; @z 888514: Delete set of ready_already. @x ready_already:=314159; @y @z 888976: Delete other set of ready_already. @x final_end: ready_already:=0; @y final_end: ; @z 889005: End the new procedure the_real_mf, and put in the actual main body code, a call to an eternal proc that will register the two tex commands "mf" and "inimf". @x end. @y end; begin register_mf_commands; end. @z 889448: Add two internal procedures to break up |close_files_and_terminate|. @x procedure close_files_and_terminate; var @!k:integer; {all-purpose index} @!lh:integer; {the length of the \.{TFM} header, in words} @!p:pointer; {runs through a list of \.{TFM} dimensions} @!x:scaled; {a |tfm_width| value being output to the \.{GF} file} begin @y procedure close_files_and_terminate; var @!k:integer; {all-purpose index} @!lh:integer; {the length of the \.{TFM} header, in words} @!p:pointer; {runs through a list of \.{TFM} dimensions} @!x:scaled; {a |tfm_width| value being output to the \.{GF} file} @# procedure tfm_finish_up_the_file; begin @; end; @# procedure gf_finish_up_the_file; begin @; end; @# begin @z 890040: Add a final carriage-return to the terminal output. @x print(log_name); print_char("."); @y print(log_name); print_char("."); print_ln; @z 890492: Call the internal procedures we've made. @x @= if (gf_prev_ptr>0)or(internal[fontmaking]>0) then begin @; @; fix_design_size; fix_check_sum; if internal[fontmaking]>0 then begin @; @; end; if gf_prev_ptr>0 then @; end @y @= if (gf_prev_ptr>0)or(internal[fontmaking]>0) then begin @; @; fix_design_size; fix_check_sum; if internal[fontmaking]>0 then begin @; tfm_finish_up_the_file; end; if gf_prev_ptr>0 then gf_finish_up_the_file; end @z 892806: (~TRAP) Change "line" to "character" in one last error message. @x begin print(" on line "); print_int(if_line); @y begin print(" near character "); print_int(if_line); @z 893292: Fix piece of unreachable code. @x begin @!init store_base_file; return;@+tini@/ print_nl("(dump is performed only by INIMF)"); return; @.dump...only by INIMF@> end; @y begin if start_like_inimf then begin store_base_file; return; end else begin print_nl("(dump is performed only by INIMF)"); @.dump...only by INIMF@> return; end; end; @z 894521: Read the default directories from the user profile; strings must be started by now, and we can't wait any longer since the next line might call start_input @x if loc"\" then start_input; {\&{input} assumed} @y read_profile_for_directories; if loc"\" then start_input; {\&{input} assumed} @z 897432: Add in the external procedure declarations. @x itself will get a new section number. @^system dependencies@> @y itself will get a new section number. @^system dependencies@> @= procedure reset_term_in(var f: alpha_file); external; {set up for input from terminal} procedure rewrite_term_out(var f: alpha_file); external; {set up for output to terminal} procedure read_the_clock(var ttime,dday,mmonth,yyear:integer); external; function file_get_pos(var f: alpha_file):integer; external; {return character count} procedure set_pool_name; external; procedure read_profile_for_directories; external; procedure set_normal_priority; external; procedure set_background_priority; external; function stuff_on_cmd_line:integer; external; procedure register_mf_commands; external; @z ÒFile: MF.changes Pavel: October 31, 1985 4:20:44 pm PST Note: In the changes below, (TRAP) indicates a change which should only be active for the TRAP test. (~TRAP) indicates a change which must not be active during the TRAP test. 015529: (TRAP) Set mem_max to 3000. @x @!mem_max=30000; {greatest index in \MF's internal |mem| array; @y @!mem_max=3000; {greatest index in \MF's internal |mem| array; @z 015899: (TRAP) Set error_line and half_error_line small, and also max_print_line. @x @!error_line=72; {width of context lines on terminal error messages} @!half_error_line=42; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=79; {width of longest text lines output; should be at least 60} @y @!error_line=64; {width of context lines on terminal error messages} @!half_error_line=32; {width of first lines of contexts in terminal error messages; should be between 30 and |error_line-15|} @!max_print_line=72; {width of longest text lines output; should be at least 60} @z 016177: (TRAP) Change screen_width and screen_depth to 100 and 200 @x @!screen_width=768; {number of pixels in each row of screen display} @!screen_depth=1024; {number of pixels in each column of screen display} @y @!screen_width=100; {number of pixels in each row of screen display} @!screen_depth=200; {number of pixels in each column of screen display} @z 017012: (TRAP) Set gf_buf_size ridiculously small. @x @!gf_buf_size=800; {size of the output buffer, must be a multiple of 8} @y @!gf_buf_size=8; {size of the output buffer, must be a multiple of 8} @z 489772: (TRAP) Make screen instructions be logged. @x @p function init_screen:boolean; begin init_screen:=false; end; @y @p function init_screen:boolean; begin init_screen:=true; end; @z 491843: (TRAP) Comment out unused variables r and c. @x @p procedure blank_rectangle(@!left_col,@!right_col:screen_col; @!top_row,@!bot_row:screen_row); var @!r:screen_row; @!c:screen_col; @y @p procedure blank_rectangle(@!left_col,@!right_col:screen_col; @!top_row,@!bot_row:screen_row); @z 493108: (TRAP) Comment out unused variable c. @x @!c:screen_col; {an index into |screen_pixel|} @y @{@!c:screen_col; {an index into |screen_pixel|}@} @z ʘ™J™&—J™JšÏbœ‡Ðezœ ™¯J™unitšœN˜Nšœ˜Jšœ=˜=—šœ˜Jšœ=˜=J˜—Jšœ˜—šœ˜šœ˜JšœH˜H—šœ˜JšœN˜N—Jšœ˜—˜S˜J˜C—˜J˜CJ˜Jšœ>˜>Jšœ˜—J˜—šœK˜Kšœ˜J˜C—šœ˜JšœN˜NJšœC˜C—Jšœ˜—šœ˜šœ˜J˜EJ˜I—šœ˜J˜ J˜ —Jšœ˜—šœ ˜ šœ˜J˜BJ˜J˜FJ˜—šœ˜J˜ J˜ —Jšœ˜—šœ$™$šœ™Jšœ?™?—šœ™Jšœ>™>—Jšœ™—šœ&˜&šœ˜Jšœ?˜?—šœ˜Jšœ?˜?—Jšœ˜—šœM˜Mšœ˜JšœG˜G—šœ˜JšœH˜H—Jšœ˜—šœX˜Xšœ˜J˜DJ˜CJ˜;J˜P—šœ˜J˜DJ˜CJ˜;J˜S—Jšœ˜—šœQ™Qšœ™J™DJ™CJ™;J™P—šœ™J™DJ™CJ™;J™P—Jšœ™—šœK˜Kšœ˜JšœD˜DJšœH˜H—šœ˜JšœE˜EJšœG˜G—Jšœ˜—šœB™Bšœ™JšœD™DJšœH™H—šœ™JšœD™DJšœG™G—Jšœ™—šœ2™2šœ™JšœG™G—šœ™JšœE™E—Jšœ™—šœN˜Nšœ˜Jšœ?˜?—šœ˜Jšœ@˜@—Jšœ˜—šœU˜Ušœ˜Jšœ7˜7JšœJ˜JJšœ ˜ —Jšœ˜Jšœ˜—šœ%˜%šœ˜J˜˜—šœ˜J˜˜—Jšœ˜—šœ&˜&šœ˜JšœL˜L—šœ˜JšœL˜L—Jšœ˜—šœE˜Ešœ˜Jšœ!˜!—šœ˜Jšœ$˜$—Jšœ˜—šœD˜Dšœ˜J˜£—šœ˜Jšœ:˜:Jšœ˜Jšœ˜Jšœ9˜9Jšœ˜Jšœ˜Jšœ7˜7Jšœ ˜ Jšœ˜Jšœ8˜8Jšœ!˜!Jšœ˜Jšœ7˜7Jšœ˜Jšœ˜Jšœ8˜8Jšœ˜—Jšœ˜—šœ,˜,šœ˜J˜=J˜J˜J˜J˜;J˜J˜J˜J˜9J˜J˜—šœ˜JšœG˜GJ˜J˜EJ˜J˜C—Jšœ˜—šœ)˜)šœ˜J˜MJ˜P—šœ˜JšœG˜GJ˜M—Jšœ˜—šœ+˜+šœ˜JšœM˜M—šœ˜Jšœ7˜7—Jšœ˜—šœD˜Dšœ˜Jšœ˜—šœ˜˜J˜ J˜—J˜J˜J˜J˜AJ˜@—Jšœ˜—šœ;˜;šœ˜Jšœ7˜7—šœ˜J˜—Jšœ˜—šœO˜Ošœ˜JšœG˜G—šœ˜Jšœi˜i—Jšœ˜—šœH˜Hšœ˜Jšœ ˜ —šœ˜Jšœ#˜#—Jšœ˜—šœ§˜§šœ˜Jšœ&˜&—šœ˜Jšœ-˜-—Jšœ˜—šœR˜Ršœ˜Jšœ˜Jšœ.˜.JšœC˜CJšœB˜B—šœ˜Jšœ8˜8Jšœ3˜3Jšœ2˜2—Jšœ˜—šœA˜Ašœ˜J˜DJ˜HJ˜ J˜J˜J˜J˜*J˜J˜#J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜—šœ˜JšœN˜NJšœY˜YJšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ.˜.Jšœ˜Jšœ#˜#Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšœ˜—šœ ˜ šœ˜Jšœ;˜;Jšœ1˜1Jšœ5˜5Jšœ)˜)Jšœ˜—šœ˜J˜3Jšœ˜J˜7Jšœ8˜8Jšœ0˜0Jšœ5˜5Jšœ-˜-Jšœ˜—Jšœ˜—šœ>˜>šœ˜Jšœ$˜$—šœ˜Jšœ+˜+—Jšœ˜—šœB˜Bšœ˜Jšœ˜—šœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—šœ&˜&šœ˜Jšœ3˜3—šœ˜Jšœ/˜/—Jšœ˜—šœ5˜5šœ˜Jšœå˜å—šœ˜Jšœ¨˜¨—Jšœ˜—šœ?˜?šœ˜J˜ï—šœ˜Jšœ™˜™—Jšœ˜—šœ°˜°šœ˜Jšœ†˜†—šœ˜Jšœ³˜³—Jšœ˜—˜?˜J˜’—˜J˜Ñ—J˜—˜B˜J˜ü—˜J˜¯—J˜—šœR˜Ršœ˜Jšœ´˜´—šœ˜Jšœµ˜µ—Jšœ˜—šœd˜dšœ˜Jšœ¤˜¤—šœ˜Jšœç˜ç—Jšœ˜—šœH˜Hšœ˜Jšœ“ ˜“ —šœ˜Jšœ¤ ˜¤ —Jšœ˜—šœ2™2šœ™Jšœ ™ Jšœ™J™—šœ™Jšœ ™ Jšœ™J™—Jšœ™—šœY˜Yšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜JšœN˜NJšœF˜FJšœ˜—šœ˜Jšœ*˜*Jšœ"˜"—Jšœ˜—šœ'˜'šœ˜Jšœ?˜?Jšœ"˜"Jšœ˜Jšœ˜Jšœ(˜(Jšœ#˜#Jšœ#˜#JšœA˜AJšœ1˜1Jšœ5˜5Jšœ˜—šœ˜Jšœ?˜?Jšœ,˜,—Jšœ˜—šœ4™4šœ™Jšœ?™?Jšœ"™"Jšœ™Jšœ™—šœ™Jšœ?™?Jšœ"™"—Jšœ™—šœ(˜(šœ˜JšœI˜IJšœ˜Jšœ'˜'Jšœ.˜.Jšœ˜Jšœ˜Jšœ'˜'Jšœ˜Jšœ%˜%Jšœ˜Jšœ1˜1Jšœ.˜.Jšœ˜Jšœ-˜-Jšœ˜Jšœ˜Jšœ˜—šœ˜JšœI˜IJšœ˜—Jšœ˜—šœ-™-šœ™Jšœ.™.—šœ™Jšœ2™2—Jšœ™—šœÎ˜Îšœ˜Jšœ,˜,—šœ˜Jšœ8˜8—Jšœ˜—šœ&˜&šœ˜J˜£—šœ˜J˜b—Jšœ˜—šœ9˜9šœ˜JšœK˜K—šœ˜JšœP˜P—Jšœ˜—šœG˜Gšœ˜Jšœ-˜-—šœ˜Jšœ-˜-JšœE˜E—Jšœ˜—šœ4˜4šœ˜Jšœ$˜$—šœ˜Jšœ˜Jšœ+˜+—Jšœ˜—šœô˜ôšœ˜Jšœ˜—šœ˜Jšœ1˜1—Jšœ˜—šœ˜šœ˜J˜J˜ —šœ˜Jšœ ˜ J˜J˜ —Jšœ˜—šœ%˜%šœ˜Jšœ$˜$Jšœ5˜5Jšœ˜JšœC˜C—šœ˜Jšœ,˜,Jšœ˜Jšœ/˜/—Jšœ˜—šœ¹˜¹šœ˜J˜å—šœ˜J˜]J˜J˜J˜J˜—Jšœ˜—šœM˜Mšœ˜Jšœµ˜µ—šœ˜JšœZ˜ZJ˜Jšœ;˜;Jšœ7˜7J˜%—Jšœ˜—šœI˜Išœ˜JšœI˜I—šœ˜JšœG˜G—Jšœ˜—šœJ˜Jšœ˜Jšœ/˜/—šœ˜Jšœ˜—Jšœ˜—šœV˜Všœ˜JšœA˜A—šœ˜JšœH˜H—Jšœ˜—šœI˜Išœ˜Jšœ<˜<—šœ˜Jšœ˜—Jšœ˜—šœ^˜^šœ˜Jšœ1˜1—šœ˜Jšœ4˜4—Jšœ˜—šœO˜Ošœ˜Jšœ;˜;Jšœ+˜+Jšœ˜Jšœ:˜:Jšœ+˜+Jšœ˜Jšœ:˜:Jšœ+˜+Jšœ˜—šœ˜JšœE˜EJšœD˜DJšœD˜D—Jšœ˜—šœ>˜>šœ˜Jšœ9˜9Jšœ ˜ —šœ˜Jšœ9˜9Jšœ ˜ J˜!—Jšœ˜—šœ/˜/šœ˜Jšœ>˜>—šœ˜Jšœ˜JšœF˜F—Jšœ˜—šœg˜gšœ˜Jšœ8˜8—šœ˜Jšœ8˜8—Jšœ˜—šœJ˜Jšœ˜Jšœ,˜,—šœ˜Jšœ3˜3—Jšœ˜—šœ-˜-šœ˜Jšœ˜Jšœ˜Jšœ0˜0—šœ˜Jšœ˜Jšœ˜Jšœ(˜(—Jšœ˜—šœ%˜%šœ˜J˜“—šœ˜J˜f—Jšœ˜—šœB˜Bšœ˜Jšœw˜wJ˜Jšœ ˜ Jšœ<˜<—šœ˜Jšœ0˜0Jšœ1˜1Jšœ ˜ Jšœ ˜ J˜J˜ËJ˜Jšœ ˜ Jšœ=˜=—Jšœ˜—šœ4˜4šœ˜Jšœ˜—šœ˜J˜bJ˜Jšœ˜Jšœ˜—Jšœ˜—šœX˜Xšœ˜Jšœ.˜.—šœ˜Jšœ˜—Jšœ˜—šœ—˜—šœ˜Jšœ6˜6Jšœ!˜!Jšœ0˜0Jšœ˜—šœ˜Jšœ˜Jšœ˜Jšœ3˜3Jšœ%˜%Jšœ4˜4Jšœ˜—Jšœ˜—šœ$˜$šœ˜Jšœ˜—Jšœ˜Jšœ˜—šœ*˜*šœ˜Jšœ˜—šœ˜Jšœ ˜ —Jšœ˜—šœ¤˜¤šœ˜Jšœ˜—šœ˜J˜J˜J˜J˜—Jšœ˜—šœL˜Lšœ˜Jšœ…˜…—šœ˜Jšœ ˜ —Jšœ˜—šœ;˜;šœ˜Jšœ%˜%—šœ˜Jšœ/˜/—Jšœ˜—šœ0˜0šœ˜Jšœ¯˜¯—šœ˜Jšœ¥˜¥—Jšœ˜—šœG˜Gšœ˜Jšœ1˜1—šœ˜Jšœ8˜8—Jšœ˜—šœ&˜&šœ˜Jšœ/˜/Jšœ8˜8Jšœ˜Jšœ˜—šœ˜Jšœ%˜%Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ6˜6Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšœ˜—šœ¤˜¤šœ˜JšœK˜K—šœ˜J˜JšœK˜K—Jšœ˜—šœ3˜3šœ˜Jšœ%˜%Jšœ˜—šœ˜Jšœ%˜%Jšœ˜J˜JšœM˜MJšœ5˜5Jšœ!˜!Jšœ8˜8Jšœ ˜ J˜HJ˜TJ˜"J˜1J˜(J˜,J˜-J˜)—Jšœ˜——…—Ú­Ã