{Begin SubSec Prettyprint} {Title Prettyprint} {Text {index *PRIMARY* Prettyprinting function definitions} {note The PRETTYPRINT package was written by W. Teitelman.} The standard way of printing out function definitions (on the terminal or into files) is to use {fn PRETTYPRINT}. {FnDef {FnName PRETTYPRINT} {FnArgs FNS PRETTYDEFLG {anonarg}} {Text {arg FNS} is a list of functions. If {arg FNS} is atomic, its value is used). The definitions of the functions are printed in a pretty format on the primary output file using the primary readtable. For example, if {lisp FACTORIAL} were defined by typing {lispcode (DEFINEQ (FACTORIAL [LAMBDA (N) (COND ((ZEROP N) 1) (T (ITIMES N (FACTORIAL (SUB1 N]} {lisp (PRETTYPRINT '(FACTORIAL))} would print out {lispcode (FACTORIAL [LAMBDA (N) (COND ((ZEROP N) 1) (T (ITIMES N (FACTORIAL (SUB1 N])} {arg PRETTYDEFLG} is {lisp T} when called from {fn PRETTYDEF} (and hence {fn MAKEFILE}). Among other actions taken when this argument is true, {fn PRETTYPRINT} indicates its progress in writing the current output file: whenever it starts a new function, it prints on the terminal the name of that function if more than 30 seconds (real time) have elapsed since the last time it printed the name of a function. {fn PRETTYPRINT} operates correctly on functions that are {prop BROKEN}, {prop BROKEN-IN}, {prop ADVISED}, or have been compiled with their definitions saved on their property lists: it prints the original, pristine definition, but does not change the current state of the function. If a function is not defined but is known to be on one of the files noticed by the file package, {fn PRETTYPRINT} loads in the definition (using {fn LOADFNS}) and prints it (except when called from {fn PRETTYDEF}). If {fn PRETTYPRINT} is given an atom which is not the name of a function, but has a value, it prettyprints the value. Otherwise, {fn PRETTYPRINT} attempts spelling correction. If all fails, {fn PRETTYPRINT} returns {lisp ({arg FN} NOT PRINTABLE)}. Note that {fn PRETTYPRINT} will return {lisp ({arg FN} NOT PRINTABLE)} if {arg FN} does not have an accessable expr definition, or if it doesn't have any definition at all. {indexX {Name NOT PRINTABLE} {Type returned by PRETTYPRINT} {Text {lisp ({arg FN} NOT PRINTABLE)} } } }} {FnDef {FnName PP} {FnArgs FN{sub 1} {ellipsis} FN{sub N}} {Type NOSPREAD NLAMBDA} {Text For prettyprinting functions to the terminal. {fn PP} calls {fn PRETTYPRINT} with the primary output file set to {lisp T} and the primary read table set to {lisp T}. The primary output file and primary readtable are restored after printing. {lisp (PP FOO)} is equivalent to {lisp (PRETTYPRINT '(FOO))}; {lisp (PP FOO FIE)} is equivalent to {lisp (PRETTYPRINT '(FOO FIE))}. }} As described above, when {fn PRETTYPRINT}, and hence {fn PP}, is called with the name of a function that is not defined, but whose definition is on a file known to the file package, the definition is automatically read in and then prettyprinted. However, if the user does not intend on editing or running the definition, but simply wants to {it see} the definition, the function {fn PF} described below can be used to simply copy the corresponding characters from the file to the terminal. This results in a savings in both space and time, since it is not necessary to allocate storage to actually read in the definition, and it is not necessary to re-prettyprint it (since the function is already in prettyprint format on the file). {FnDef {FnName PF} {FnArgs FN FROMFILES TOFILE} {Type NOSPREAD NLAMBDA} {Text Copies the definition of {arg FN} found on each of the files in {arg FROMFILES} to {arg TOFILE}. If {arg TOFILE}={lisp NIL}, defaults to {lisp T}. If {arg FROMFILES}={lisp NIL}, defaults to {lisp (WHEREIS {arg FN} NIL T)} (see {PageRef Fn WHEREIS}). The typical usage of {fn PF} is simply to type "{lisp PF {arg FN}}". {fn PF} prints a message if it can't find a file on {arg FROMFILES}, or it can't find the function {arg FN} on a file. }} When printing to the terminal, {fn PF} performs several transformations on the characters in the file that comprise the definition for {arg FN}: (1) font information is stripped out (except in Interlisp-D, whose display supports multiple fonts); (2) occurrences of the {var CHANGECHAR} ({PageRef Var CHANGECHAR}) are not printed; (3) since functions typically tend to be printed to a file with a larger linelength than when printing to a terminal, the number of leading spaces on each line is cut in half (unless {var PFDEFAULT}{Index PFDEFAULT Var} is {lisp T}; initially {lisp NIL}); and (4) comments are elided, if {var **COMMENT**FLG} is non-{lisp NIL} (see {PageRef Var **COMMENT**FLG}). {FnDef {FnName SEE} {FnArgs FROMFILE TOFILE} {Type NOSPREAD NLAMBDA} {Text Copies all of the text from {arg FROMFILE} to {arg TOFILE} (defaults to {lisp T}), processing all text as {lisp PF} does. Used to display the contents of files on the terminal. }} {FnDef {FnName PP*} {FnArgs X} {Type NOSPREAD NLAMBDA} } {FnDef {FnName PF*} {FnArgs FN FROMFILES TOFILE} {Type NOSPREAD NLAMBDA} } {FnDef {FnName SEE*} {FnArgs FROMFILE TOFILE} {Type NOSPREAD NLAMBDA} {Text These functions operate exactly like {fn PP}, {fn PF}, and {lisp SEE}, except that they bind {var **COMMENT**FLG} to {lisp NIL}, so comments are printed in full (see {PageRef Var **COMMENT**FLG}). }} While the function {fn PRETTYPRINT} prints entire function definitions, the function {fn PRINTDEF} can be used to print parts of functions, or arbitrary Interlisp structures: {FnDef {FnName PRINTDEF} {FnArgs EXPR LEFT DEF TAILFLG FNSLST FILE} {Text Prints the expression {arg EXPR} in a pretty format on {arg FILE} using the primary readtable. {arg LEFT} is the left hand margin ({fn LINELENGTH} determines the right hand margin). {fn PRINTDEF} initially performs {lisp (TAB {arg LEFT} T)}, which means to space to position {arg LEFT}, unless already beyond this position, in which case it does nothing. {arg DEF}={lisp T} means {arg EXPR} is a function definition, or a piece of one. If {arg DEF}={lisp NIL}, no special action is taken for {lisp LAMBDA}'s, {fn PROG}'s, {fn COND}'s, comments, CLISP, etc. {arg DEF} is {lisp NIL} when {fn PRETTYDEF} calls {fn PRETTYPRINT} to print variables and property lists, and when {index PRINTDEF FN}{fn PRINTDEF} is called from the editor via the command {index PPV EditCom}{editcom PPV}. {arg TAILFLG}={lisp T} means {arg EXPR} is interpreted as a tail of a list, to be printed without parentheses. {arg FNSLST} is for use for printing with multiple fonts ({PageRef Term Fonts}). {fn PRINTDEF} prints occurrences of any function in the list {arg FNSLST} in a different font, for emphasis. {fn MAKEFILE} passes as {arg FNSLST} the list of all functions on the file being made. }} {Begin SubSec Comment Feature} {Title Comment Feature} {Text {Tag CommentFeature} {index *PRIMARY* * (use in comments)} {index *PRIMARY* Comments in functions} A facility for annotating Interlisp functions is provided in {fn PRETTYPRINT}. Any expression beginning with the atom {lisp *} is interpreted as a comment and printed in the right margin. Example: {lispcode (FACTORIAL [LAMBDA (N) (* COMPUTES N!) (COND ((ZEROP N) (* 0!=1) 1) (T (* RECURSIVE DEFINITION: N!=N*N-1!) (ITIMES N (FACTORIAL (SUB1 N])} {index *PRIMARY* * Fn} These comments actually form a part of the function definition. Accordingly, {lisp *} is defined as an nlambda nospread function that returns its argument, similar to {fn QUOTE}. When running an interpreted function, {lisp *} is entered the same as any other Interlisp function. Therefore, comments should only be placed where they will not harm the computation, i.e., where a quoted expression could be placed. For example, writing {lispcode (ITIMES N (FACTORIAL (SUB1 N)) (* RECURSIVE DEFINITION))} in the above function would cause an error when {lisp ITIMES} attempted to multiply {lisp N}, {lisp N-1!}, and {lisp RECURSIVE}. For compilation purposes, {lisp *} is defined as a macro which compiles into no instructions (unless the comment has been placed where it has been used for value, in which case the compiler prints an appropriate error message and compiles {lisp *} as {fn QUOTE}). Thus, the compiled form of a function with comments does not use the extra atom and list structure storage required by the comments in the source (interpreted) code. This is the way the comment feature is intended to be used. A comment of the form {lisp (* E {arg X})} causes {arg X} to be evaluated at prettyprint time, as well as printed as a comment in the usual way. For example, {lisp (* E (RADIX 8))} as a comment in a function containing octal numbers can be used to change the radix to produce more readable printout.{index E (use in comments)} The comment character {lisp *} is stored in the variable {var COMMENTFLG}. The user can set it to some other value, e.g. "{lisp ;}", and use this to indicate comments. {VarDef {Name COMMENTFLG} {Text If {fn CAR} of an expression is {fn EQ} to {var COMMENTFLG}, the expression is treated as a comment by {fn PRETTYPRINT}. {var COMMENTFLG} is initialized to {lisp *}.{index * (use in comments)} Note that whatever atom is chosen for {var COMMENTFLG} should also have an appropriate function definition and compiler macro, for example, by copying those of {lisp *}. }} {index **COMMENT** (printed by system)} {indexX {Name COMMENT} {Type printed by system} {Text {lisp **COMMENT**}} } Comments are designed mainly for documenting {it listings}. Therefore, when prettyprinting to the terminal, comments are suppressed and printed as the string {lisp **COMMENT**}. The value of {var **COMMENT**FLG} determines the action. {indexX {Name COMMENT**FLG} {Type Variable} {Text {lisp **COMMENT**FLG}} } {VarDef {Name **COMMENT**FLG} {Text If {var **COMMENT**FLG} is {lisp NIL}, comments are printed. Otherwise, the value of {var **COMMENT**FLG} is printed. Initially {lisp " **COMMENT** "}. }} {FnDef {FnName COMMENT1} {FnArgs L {anonarg}} {Text Prints the comment {arg L}. {fn COMMENT1} is a separate function to permit the user to write prettyprint macros ({PageRef Var PRETTYPRINTMACROS}) that use the regular comment printer. For example, to cause comments to be printed at a larger than normal linelength, one could put an entry for {lisp *} on {var PRETTYPRINTMACROS}: {lispcode (* LAMBDA (X) (RESETFORM (LINELENGTH 100) (COMMENT1 X)))} This macro resets the line length, prints the comment, and then restores the line length. {fn COMMENT1} expects to be called from within the environment established by {fn PRINTDEF}, so ordinarily the user should call it {it only} from within prettyprint macros. }} }{End SubSec Comment Feature} {Begin SubSec Comment Pointers} {Title Comment Pointers} {Text {Tag CommentPointer} {index *PRIMARY* Comment pointers} {index *PRIMARY* * (as a read macro)} {index *PRIMARY* * (as a prettyprint macro)} For a well-commented collection of programs, the list structure, atom, and print name storage required to represent the comments in core can be significant. If the comments already appear on a file and are not needed for editing, a significant savings in storage can be achieved by simply leaving the text of the comment on the file when the file is loaded, and instead retaining in core only a {it pointer} to the comment. When this feature is enabled, {lisp *} is defined as a read macro ({PageRef Tag ReadMacros}) in {var FILERDTBL}{index FILERDTBL Var} which, instead of reading in the entire text of the comment, constructs an expression containing (1) the name of the file in which the text of the comment is contained, (2) the address of the first character of the comment, (3) the number of characters in the comment, and (4) a flag indicating whether the comment appeared at the right hand margin or centered on the page. For output purposes, {lisp *} is defined on {var PRETTYPRINTMACROS} ({PageRef Var PRETTYPRINTMACROS}) so that it prints the comments represented by such pointers by simply copying the corresponding characters from one file to another, or to the terminal. Normal comments are processed the same as before, and can be intermixed freely with comment pointers. The comment pointer feature is controlled by the function {fn NORMALCOMMENTS}. {FnDef {Name NORMALCOMMENTS} {Args FLG} {Text If {arg FLG} is {lisp NIL}, the comment pointer feature is enabled. If {arg FLG} is {lisp T}, the comment pointer feature is disabled (the default). {fn NORMALCOMMENTS} can be changed as often as desired. Thus, some files can be loaded normally, and others with their comments converted to comment pointers. }} For convenience of editing selected comments, an edit macro, {editcom GET*}{index GET* EditCom}, is included, which loads in the text of the corresponding comment. The editor's {fn PP*} command, in contrast, prints the comment {it without} reading it by simply copying the corresponding characters to the terminal. {editcom GET*} is defined in terms of {fn GETCOMMENT}: {FnDef {FnName GETCOMMENT} {FnArgs X DESTFL {anonarg}} {Text If {arg X} is a comment pointer, replaces {arg X} with the actual text of the comment, which it reads from its file. Returns {arg X} in all cases. If {arg DESTFL} is non-{lisp NIL}, it is the name of an open file, to which {fn GETCOMMENT} copies the comment; in this case, {arg X} remains a comment pointer, but it has been changed to point to the new file (unless {fn NORMALCOMMENTS}{index NORMALCOMMENTS Fn} has been set to {lisp DONTUPDATE}). }} {FnDef {FnName PRINTCOMMENT} {FnArgs X} {Text Defined as the prettyprint macro for {lisp *}: copies the comment to the primary output file by using {fn GETCOMMENT}. }} {FnDef {FnName READCOMMENT} {FnArgs FL RDTBL LST} {Text Defined as the read macro for {lisp *} in {lisp FILERDTBL}: if {var NORMALCOMMENTSFLG} is {lisp NIL}, it constructs a comment pointer, unless it believes the expression beginning with {lisp *} is not actually a comment, e.g., if the next atom is "{lisp .}" or {lisp E}. }} Note that a certain amount of care is required in using the comment pointer feature. Since the text of the comment resides on the file pointed to by the comment pointer, that file must remain in existence as long as the comment is needed. {fn GETCOMMENT} helps out by changing the comment pointer to always point at the most recent file that the comment lives on. However, if the user has been performing repeated {fn MAKEFILE}'s ({PageRef Fn MAKEFILE}) in which differing functions have changed at each invocation of {fn MAKEFILE}, it is possible for the comment pointers in memory to be pointing at several versions of the same file, since a comment pointer is only updated when the function it lives in is prettyprinted, not when the function has been copied verbatim to the new file. This can be a problem for file systems that have a built-in limit on the number of versions of a given file that will be made before old versions are expunged. In such a case, the user should set the version retention count of any directories involved to be infinite. {fn GETCOMMENT} prints an error message if the file that the comment pointer points at has disappeared. Similarly, one should be cognizant of comment pointers in sysouts, and be sure to retain any files thus pointed to. When using comment pointers, the user should also not set {var PRETTYFLG} ({PageRef Var PRETTYFLG}) to {lisp NIL} or call {fn MAKEFILE} with option {lisp FAST}, since this will prevent functions from being prettyprinted, and hence not get the text of the comment copied into the new file. If the user changes the value of {var COMMENTFLG}{index COMMENTFLG Var} but still wishes to use the comment pointer feature, the new {var COMMENTFLG} should be given the same read-macro definition in {var FILERDTBL} as {lisp *} has, and the same entry be put on {var PRETTYPRINTMACROS}. For example, if {var COMMENTFLG} is reset to be "{lisp ;}", then {lisp (SETSYNTAX '; '* FILERDTBL)} should be performed, and {lisp (; . PRINTCOMMENT)} added to {var PRETTYPRINTMACROS}. }{End SubSec Comment Pointers} {Begin SubSec Converting Comments to Lower Case} {Title Converting Comments to Lower Case} {Text {index *PRIMARY* Lower case comments} {Tag LowerCaseComments} This section is for users using terminals without lower case, who nevertheless would like their comments to be converted to lower case for more readable listings. If the second atom in a comment is {lisp %%}, the text of the comment is converted to lower case so that it looks like English instead of Lisp. Note that comments are converted {it only} when they are actually written to a file by {fn PRETTYPRINT}. The algorithm for conversion to lower case is the following: If the first character in an atom is {lisp ^},{index ^ (use in comments)} do not change the atom (but remove the {lisp ^}). If the first character is {lisp %},{index % (use in comments)} convert the atom to lower case. Note that the user must type {lisp %%} as {lisp %} is the escape character. If the atom (minus any trailing punctuation marks) is an Interlisp word (i.e., is a bound or free variable for the function containing the comment, or has a top level value, or is a defined function, or has a non-{lisp NIL} property list), do not change it. Otherwise, convert the atom to lower case. Conversion only affects the upper case alphabet, i.e., atoms already converted to lower case are not changed if the comment is converted again. When converting, the first character in the comment and the first character following each period are left capitalized. After conversion, the comment is physically modified to be the lower case text minus the {lisp %%}{index %% (use in comments)} flag, so that conversion is thus only performed once (unless the user edits the comment inserting additional upper case text and another {lisp %%} flag). {VarDef {Name LCASELST} {Text Words on {var LCASELST} will always be converted to lower case. {var LCASELST} is initialized to contain words which are Interlisp functions but also appear frequently in comments as English words ({lisp AND}, {lisp EVERY}, {lisp GET}, {lisp GO}, {lisp LAST}, {lisp LENGTH}, {lisp LIST}, etc.). Therefore, if one wished to type a comment including the lisp fuction {fn GO}, it would be necessary to type {lisp ^GO} in order that it might be left in upper case. }} {VarDef {Name UCASELST} {Text Words on {var UCASELST} (that do not appear on {var LCASELST}) will be left in upper case. {var UCASELST} is initialized to {lisp NIL}. }} {VarDef {Name ABBREVLST} {Text {var ABBREVLST} is used to distinguish between abbreviations and words that end in periods. Normally, words that end in periods and occur more than halfway to the right margin cause carriage-returns. Furthermore, during conversion to lowercase, words ending in periods, except for those on {var ABBREVLST}, cause the first character in the {it next} word to be capitalized. {var ABBREVLST} is initialized to the upper and lower case forms of {lisp ETC.}, {lisp I.E.}, and {lisp E.G.}. }} }{End SubSec Converting Comments to Lower Case} {Begin SubSec Special Prettyprint Controls} {Title Special Prettyprint Controls} {Text {VarDef {Name PRETTYTABFLG} {Text In order to save space on files, tabs are used instead of spaces for the inital spaces on each line, assuming that each tab corresponds to 8 spaces. This results in a reduction of file size by about 30%. Tabs are not used if {var PRETTYTABFLG} is set to {lisp NIL} (initially {lisp T}). }} {indexX {Name RPARS} {Type Variable} {Text {lisp #RPARS}} } {VarDef {Name #RPARS} {Text Controls the number of right parentheses necessary for square bracketing to occur.{index Square brackets inserted by PRETTYPRINT}{index [,] inserted by PRETTYPRINT} If {var #RPARS}={lisp NIL}, no brackets are used. {var #RPARS} is initialized to 4. }} {VarDef {Name FIRSTCOL} {Text The starting column for comments. Comments run between {var FIRSTCOL} and the line length set by {fn LINELENGTH} ({PageRef Fn LINELENGTH}). If a word in a comment ends with a "{lisp .}" and is not on the list {index ABBREVLST Var}{var ABBREVLST}, and the position is greater than halfway between {var FIRSTCOL} and {fn LINELENGTH}, the next word in the comment begins on a new line. Also, if a list is encountered in a comment, and the position is greater than halfway, the list begins on a new line. }} {VarDef {Name PRETTYLCOM} {Text If a comment has more than {var PRETTYLCOM} elements (using {fn COUNT}), it is printed starting at column 10, instead of {var FIRSTCOL}. Comments are also printed starting at column 10 if their second element is also a {lisp *}, i.e., comments of the form {lisp (* * --)}. }} {indexX {Name CAREFULCOLUMNS} {Type Variable} {Text {lisp #CAREFULCOLUMNS}} } {VarDef {Name #CAREFULCOLUMNS} {Text In the interests of efficiency, {fn PRETTYPRINT} approximates the number of characters in each atom, rather than calling {fn NCHARS}, when computing how much will fit on a line. This procedure works satisfactorily in most cases. However, users with unusually long atoms in their programs, e.g., such as produced by {fn CLISPIFY}, may occasionlly encounter some glitches in the output produced by {fn PRETTYPRINT}. The value of {var #CAREFULCOLUMNS} tells {fn PRETTYPRINT} how many columns (counting from the right hand margin) in which to actually compute {fn NCHARS} instead of approximating. Setting {var #CAREFULCOLUMNS} to 20 or 30 will eliminate the glitches, although it will slow down {fn PRETTYPRINT} slightly. {var #CAREFULCOLUMNS} is initially 0. }} {FnDef {FnName WIDEPAPER} {FnArgs FLG} {Text {lisp (WIDEPAPER T)} sets {var FILELINELENGTH}{index FILELINELENGTH Var} ({PageRef Var FILELINELENGTH}), {index FIRSTCOL Var}{var FIRSTCOL}, and {index PRETTYLCOM Var}{var PRETTYLCOM} to large values appropriate for pretty printing files to be listed on wide paper. {lisp (WIDEPAPER)} restores these parameters to their initial values. {fn WIDEPAPER} returns the previous setting of {arg FLG}. }} {note should PRETTYFLG be moved near PRINTDEF (in PRETTYDEF section) ??} {VarDef {Name PRETTYFLG} {Text If {var PRETTYFLG} is {lisp NIL}, {index PRINTDEF FN}{fn PRINTDEF} uses {fn PRIN2} instead of prettyprinting. This is useful for producing a fast symbolic dump (see the {lisp FAST} option of {fn MAKEFILE}, {PageRef Fn MAKEFILE}). Note that the file loads the same as if it were prettyprinted. {var PRETTYFLG} is initially set to {lisp T}. {var PRETTYFLG} should not be set to {lisp NIL} if comment pointers ({PageRef tag CommentPointer}) are being used. }} {VarDef {Name CLISPIFYPRETTYFLG} {Text Used to inform {fn PRETTYPRINT} to call {fn CLISPIFY} on selected function definitions before printing them (see {PageRef Var CLISPIFYPRETTYFLG}). }} {VarDef {Name PRETTYPRINTMACROS} {Text An association-list that enables the user to control the formatting of selected expressions. {fn CAR} of each expression being {fn PRETTYPRINT}ed is looked up on {var PRETTYPRINTMACROS}, and if found, {fn CDR} of the corresponding entry is applied to the expression. If the result of this application is {lisp NIL}, {fn PRETTYPRINT} ignores the expression; i.e., it prints nothing, assuming that the prettyprintmacro has done any desired printing. If the result of applying the prettyprint macro is non-{lisp NIL}, the result is prettyprinted in the normal fashion. This gives the user the option of computing some other expression to be prettyprinted in its place. Note: "prettyprinted in the normal fashion" includes processing prettyprint macros, unless the prettyprint macro returns a structure {lisp EQ} to the one it was handed, in which case the potential recursion is broken. }} {VarDef {Name PRETTYPRINTYPEMACROS} {Text A list of elements of the form {lisp ({arg TYPENAME} . {arg FN})}. For types other than lists and atoms, the type name of each datum to be prettyprinted is looked up on {var PRETTYPRINTYPEMACROS}, and if found, the corresponding function is applied to the datum about to be printed, instead of simply printing it with {fn PRIN2}. }} {VarDef {Name PRETTYEQUIVLST} {Text An association-list that tells {fn PRETTYPRINT} to treat a {fn CAR}-of-form the same as some other {fn CAR}-of-form. For example, if {lisp (QLAMBDA . LAMBDA)} appears on {var PRETTYEQUIVLST}, then expressions beginning with {lisp QLAMBDA} are prettyprinted the same as {lisp LAMBDA}s. Currently, {var PRETTYEQUIVLST} only allows (i.e., supports in an interesting way) equivalences to forms that {fn PRETTYPRINT} internally handles. Equivalence to forms for which the user has specified a prettyprint macro should be made by adding further entries to {var PRETTYPRINTMACROS} }} {VarDef {Name CHANGECHAR} {Text If non-{lisp NIL}, and {fn PRETTYPRINT} is printing to a file or display terminal, {fn PRETTYPRINT} prints {var CHANGECHAR} in the right hand margin while printing those expressions marked by the editor as having been changed (see {PageRef Tag EditorChangeMarks}). {var CHANGECHAR} is initially {lisp |}.{index *PRIMARY* | (change character)} }} }{End SubSec Special Prettyprint Controls} }{End SubSec Prettyprint} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) %Ö     <‚cÉ zº