APLASCII Update File 26 Dec 1995 rev. 3 Nov 1997 This file updates APLASCII version 1.4 to fix a few bugs and allow it to read transliterated data contained in .html files. If you have a later version of APLASCII, you probably don't need to use this file. To update your A2A workspace (the installed APLASCII workspace), execute the following commands: )LOAD A2A LOADWS'A2AUPDT.TXT' - read this file {quad}FX CR - update DEFINEFNS )ERASE CR )SAVE (APL.68000 Users: See note below for special workaround instructions!) When reading .html files into APL, use a statement such as: DEFINEFNS UNHTMLIZE TFREAD 'filename.html' This translation will be performed automatically in future versions of APLASCII. ====================================================================== APL.68000 Users: Due to a bug in #EX, the original version of DEFINEFNS does not work properly in some versions of APL.68000--it puts all objects in CRx and VARx variables. The revised version below fixes the problem, but you may need to execute some extra statements to get the objects in this update file defined in the workspace. Start with the regular procedure listed above. If LOADWS displays: Unable to define UNHTMLIZE. #CR stored in variable CR1. Unable to define {delta_}TEXTREPL. #CR stored in variable CR2. Unable to assign variable CR. Value stored in VAR1. Then finish the update by executing the following statements: {quad}FX CR1 {quad}FX CR2 {quad}FX VAR1 )ERASE CR1 CR2 VAR1 )SAVE Incidentally, the problem is that #EX is returning 1 if it erased the name or 0 if the name was already undefined. It should instead return 1 if the name is now available for use, regardless of whether or not the name was initially undefined. Thanks to Dre Nierop for reporting this problem. ====================================================================== Here are the new and changed objects: {del} Z{<-}UNHTMLIZE A;T [1] @Converts .html text {omega} to plain text (enough for APLASCII's {+ +}needs) [2] {->}(2{/=}{rho}{rho}Z{<-}A)/L1 [3] Z{<-}{delta_}TCNL {delta_}MTOV A @convert to vector [4] L1:T{<-}'&{&}amp;&{&}&{&}lt;&<&{&}gt;&>&
&&&' @recognize {+ +}lowercase [5] T{<-}T,'&{&}AMP;&{&}&{&}LT;&<&{&}GT;&>&
&&&' @or uppercase,{+ +} but not mixes [6] @ We delete
s because we expect them to appear mixed in with [7] @ the APL code. We don't bother deleting other tags. [8] Z{<-}T {delta_}TEXTREPL Z [9] {->}(2{/=}{rho}{rho}A)/0 [10] Z{<-}{delta_}VTOM Z @restore original rank {del} Note: The following version of TEXTREPL includes a correction for a bug that was found on May 25, 1996: {del} Z{<-}A {delta_}TEXTREPL B;C;D;E;F;H;I;J;K;N;R;T;V;W;X [1] @Replaces phrases in text {omega} as directed by {alpha} [2] @ Arguments: [3] @ B - a character vector, the text to change [4] @ A - a segmented string containing the old phrases to search for [5] @ and the new phrases to replace them with. E.g., [6] @ '/OLD1/NEW1/OLD2/NEW2/OLD3/NEW3' [7] @ Result: [8] @ Z - like B, but with the changes made [9] @ [10] @ Details/limitations: [11] @ - If one old string is a prefix of another, the one occuring first [12] @ in A takes precedence. Thus, when searching for both ABC and ABCD [13] @ in the alphabet, ABC will be found instead of ABCD. [14] [15] @ Convert the phrase list to a matrix, using the delimiter for fill: [16] D{<-}''{rho}A @delimiter [17] A{<-}1{rotate}A @put delims at end of each string [18] I{<-}(A=D)/{iota}{rho}A [19] N{<-}I-{neg}1{drop}0,I @num chars in each string, incl. delim [20] R{<-}({rho}A){rho}1 [21] R[I]{<-}({max}/N)-N @how many copies to make of each delimiter [22] A{<-}R/A @replicate delimiters for uniform row length [23] A{<-}(({rho}N),0{max}{neg}1+{max}/N){rho}A @matrix with string on {+ +}each row [24] [25] {->}(2|1{take}{rho}A)/L6 @must be even number of strings [26] F{<-}A[{neg}1+I{<-}2{times}{iota}.5{times}1{take}{rho}A;]@old {+ +}phrases to find [27] W{<-}+/{or}\{reverse}F{/=}D@width of each old phrase [28] {->}(0{epsilon}W)/L7 @old strings must not be empty [29] F{<-}((1{take}{rho}F),2{max}{max}/W){take}F,D@delete trailing {+ +}delimiter cols [30] R{<-}A[I;]@new replacement phrases [31] [32] H{<-}1{drop}{rho}F [33] B{<-}B,H{rho}D@padding fill for matches near end [34] I{<-}I/{iota}{rho}I{<-}B{epsilon}F[;1]@places where first letters occur [35] J{<-}1 [36] L1:{->}(H}(D{epsilon}F[;J])/L2@ quit if we've reached a padding char [38] I{<-}(B[I+J-1]{epsilon}F[;J])/I@ keep places where following char {+ +}matches [39] {->}L1@Endloop [40] L2:X{<-}B[({rho}B){min}I{jot}.+{neg}1+{iota}1{drop}{rho}F]@text {+ +}following the starts [41] [42] @ Do the phrase lookup [43] X{<-}(1{take}{rho}F){slashbar}X@dims [start{times}old;string] [44] F{<-}({rho}X){rho}F [45] T{<-}(({rho}I),{rho}W){rho}^/(X=F){or}F=D@dims [start;old] [46] J{<-}(<\T)+.{times}{iota}{rho}W@index of old phrase starting at each {+ +}location I [47] [48] I{<-}(T{<-}J{/=}0)/I@ignore nonmatches [49] J{<-}T/J [50] V{<-},T{<-}I,[1.5]I+W[J]@start and just-past-end of phrases [51] {->}(({iota}{rho},V)^.={gradeup},V)/L5@jump if no overlaps [52] [53] @ Deal with overlapping hits. For example, if we find both ABC and CDE [54] @ in ABCDEFG, CDE should be eliminated. If we find ABC, CDE, and EFG, [55] @ CDE should be excluded, but EFG should not because it overlaps only [56] @ an excluded string. Sheesh! Try to do THIS without looping! [57] C{<-}(F{<-}''{rho}{rho}T){take}1 [58] V{<-}T[K{<-}1;2]@V points just past the end of last non-eliminated hit [59] L3:{->}(F }(T[K;1] }L3@Endloop [64] L4:I{<-}C/I [65] J{<-}C/J [66] [67] L5:C{<-}({rho}B){rho}1 [68] C[I+W[J]]{<-}0@put 0 just past end of each old phrase [69] C[I]{<-}~C[I]@put (usually) 0 at start of each phrase [70] @ {first} Normally each phrase results in two zeros, except in the case [71] @ of two immediately adjacent phrases, in which case we want to [72] @ omit the 2nd 0 for the first phrase. Used to use C[I,I+W[J]]{<-}0, [73] @ but that was wrong. [74] B{<-}(=\C)/B@delete the old phrases [75] I{<-}I-+\0,W[{neg}1{drop}J]@starting posns in compressed B [76] V{<-}+/{or}\{reverse}R{/=}D@width of each new phrase [77] I{<-}(T{<-}V[J]{/=}0)/I@ignore empty replacements [78] J{<-}T/J [79] I{<-}I++\0,V[{neg}1{drop}J]@starting posns in expanded B [80] E{<-}(({rho}B)++/V[J]){rho}0 [81] E[I+V[J]]{<-}1@put 1 just past end of where replacements go [82] E[I]{<-}~E[I] @put (usually) 1 at start of each posn [83] @ {first} Same consideration as above for adjacent replacements. [84] B{<-}(~E{<-}{/=}\E)\B@insert blanks for new phrases [85] T{<-}(,{reverse}{or}\{reverse}T{/=}D)/,T{<-}R[J;]@replacement phrases [86] B[E/{iota}{rho}E]{<-}T@insert the new phrases [87] Z{<-}(-H){drop}B@drop padding we added [88] {->}0 [89] [90] L6:#{<-}'Left argument must have an even number of strings.' [91] {->}0 [92] L7:#{<-}'Empty old phrase is not allowed.' [93] {->}0 [94] @ Copyright (c) 1995-96 by Jim Weigang {del} Add the new function names to GRPA2A: {del}: GRPA2A{<-}GRPA2A {delta_}OVER {delta_}VTOM'/UNHTMLIZE/{delta_}TEXTREPL' While we're at it, update one function to correct a small bug: {del} Z{<-}{delta_}FNNAME H;I;P [1] @Extracts function or operator name from header line {omega} [2] @ The argument is the header line, without any leading [0] or {del} [3] {->}(~P{<-}'('{epsilon}H)/L1 @ If it's an operator [e.g., Z{+ +}{<-}(F OP) B], [4] H{<-}({neg}1+H{iota}')'){take}H [5] H{<-}(H{iota}'('){drop}H @ get the stuff between the {+ +}parens [6] {->}L2 @ Else, it's a function, [7] L1:H{<-}(('{<-}'{epsilon}H){times}H{iota}'{<-}'){drop}H [8] H{<-}({neg}1+{min}/H{iota}';@'){take}H @ get the stuff {+ +}between {<-} and ; (or @) [9] L2:H[(H='{rightbrace}')/{iota}{rho}H]{<-}' ' @ change {leftbrace}A{+ +}{rightbrace}FOO B to {leftbrace}A FOO B [10] H{<-}{delta_}VTOM' ',H [11] H{<-}(H{or}.{/=}' '){slashbar}H @ matrix of names in H [12] I{<-}(1 1 2,[.5]1 2 2)[1+P;''{rho}{rho}H] @ row containing the fn/op {+ +}name [13] Z{<-}(Z{/=}' ')/Z{<-}H[I;] {del} And install a revised version of DEFINEFNS to fix a problem that affects the APL.68000 system. (We can't define DEFINEFNS directly because it'll be on the stack, so we define it here as variable CR and have the user finish the job.) {del}. CR{<-}167 78{rho}' {delta_}Z{<-}DEFINEFNS {delta_}M;{delta_}C;{del{+ +}ta_}E;{delta_}F;{delta_}G;{delta_}H;{delta_}I;{delta_}K;{delta_}N;{delta_}{+ +}R;{delta_}S;{delta_}T;{delta_}V;{delta_}W;{delta_}ERR;{delta_}NOUNWRAP;#IO{+ +} @Defines functions and variables found in message {omega} {+ +} @ Arguments: {+ +} @ {delta_}M - the transliterated message from which {+ +}function/variable @ definitions should be extracted. {+ +}May be either a character @ matrix or a newline-delimited {+ +}vector. @ {delta_}QIO - (optional global) {+ +}If this var is defined, any value of #IO @ found in the me{+ +}ssage will be assigned to {delta_}QIO. If it isn''t @ def{+ +}ined, #IO will be placed in one of the VARi variables. @ Results{+ +}: @ {{+ +}delta_}Z - character matrix containing the names of objects that {+ +} @ were defined in the workspace. {+ +} @ {delta_}QIO - (global) value of #IO found in the message. (S{+ +}ee above.) @ {+ +} @ A line that begins with either [0] or {del} (as{+ +} the first nonblank @ character) marks the start of a defin{+ +}ition in the message. @ A line that begins with {del}. mark{+ +}s the start of a variable definition. @ A line that begins with {de{+ +}l}: marks the start of a statement to execute. @ A line that begins {+ +}with {del}- marks a separator (start/end of WS, etc.) @ A definitio{+ +}n ends with a blank line, a closing {del}, or the end of the @ m{+ +}essage. @{+ +} {+ +} @ If a function can''t be defined, its #CR is placed in a global {+ +} @ variable CR (where is an integer). {+ +} @ If a variable can''t be defined, its value is placed in a gl{+ +}obal @ variable VAR. {+ +} @ {+ +} #IO{<-}1 {+ +} {delta_}Z{<-}0 0{rho}'''' {+ +} {->}(~''{del}''{epsilo{+ +}n}{delta_}M)/{delta_}1 {+ +} {delta_}OUT''The DEFINEFNS argument must be in transliterated{+ +} form.'' {->}0 {+ +} {delta_}1:{->}(2={rho}{rho}{delta_}M)/{del{+ +}ta_}2 @ If not a matrix, {delt{+ +}a_}M{<-}{delta_}VTOM {delta_}TCNL,{delta_}M @ break on CRs {+ +} {delta_}2:{delta_}M{<-}{delta_}LJUST {delta_}{+ +}M {delta_}F{+ +}{<-}((1{take}{rho}{delta_}M),3{max}{neg}2+1{drop}{rho}{delta_}TTABM){take}{+ +}{delta_}M {delta_}NOUNWRAP{{+ +}<-}1 @ prevent ASCII2APL from unwrapping lines {de{+ +}lta_}T{<-}{delta_}MUTE''{delta_}F{<-}ASCII2APL {delta_}F'' @ get the f{+ +}irst few symbols on each line @ {first} Use {delta_}MUTE to suppres{+ +}s error messages from chopped keywords {delta_}NOUNWRAP{<-}{+ +}0 @ turn line unwrapping on {->}(0{+ +}{epsilon}{rho}{delta_}F)/0 {+ +} {delta_}F{<-}(0 3{max}{rho}{delta_}F){take}{delta_}F {+ +} {delta_}S{<-}{+ +}({delta_}F[;1]=''{del}''){or}{delta_}F[;{iota}3]^.=''[0]'' @ find defn sta{+ +}rts {delta_}E{<-}{delta_}S{or}{delta_}F[;1]='' {+ +}'' @ and ends @ {+ +} {delta_{+ +}}3:{delta_}I{<-}{delta_}S{iota}1 @ Loop for each objec{+ +}t {->}({delta_}I>{rho}{delta_}S)/0 {+ +} @ quit if no more objs {delta_}N{<-}({delta_}{+ +}I{drop}{delta_}E){iota}1 @ num lines in defn {+ +} {delta_}R{<-}{delta_}C{<-}{delta_}M[{delta_}I+{neg}1+{iota{+ +}}{delta_}N;] @ the defn {del{+ +}ta_}C{<-}{delta_}TCNL {delta_}MTOV {delta_}C @ work with it{+ +} as a vector {delta_}K{<-}'''' {+ +} @ Convert to APL, and captu{+ +}re unrecognized-keyword messages: ''{delta_}K{<-}{delta_}{+ +}MUTE''''{delta_}C{<-}ASCII2APL {delta_}C''''''{delta_}WITHTTM {delta_}TTAB{+ +}M {delta_}OVER {delta_}TCNL,'' {leftbrace}nl{rightbrace}'' @ {+ +}{first} We untransliterate objects one at a time because we don''t want th{+ +}e @ matrix {delta_}M to become extremely wide from unwrapping the{+ +} continuation @ lines in long variable definitions. {+ +} {delta_}K{<-}({delta_}K{iota}{delta_}TCNL){drop}{d{+ +}elta_}K{<-}({delta_}K{iota}{delta_}TCNL){drop}{delta_}K @ list of bad k{+ +}eywords, if any {delta_}S[{delta_}I,(~(2{drop}3{take}{delta_}{+ +}C){epsilon}''.:-'')/({rho}{delta_}S){min}{delta_}I+{delta_}N]{<-}0 @ ma{+ +}rk this one as processed @ {first} If this object is a function, do{+ +}n''t consider the ending line @ (which may be a closing {de{+ +}l}) to be the start of an object. @ {+ +} @ {del}- prefix -- {+ +}marker; check version number {->}(''{del{+ +}}-''{or}.{/=}1{drop}3{take}{delta_}C)/{delta_}6 {+ +} {delta_}C{<-}{delta_}DLB({delta_}C{iota}''{+ +} ''){drop}{delta_}C {+ +} {delta_}V{<-}''APLASCII version:'' {+ +} {->}({delta_}V{or}.{/=}({rho}{delta_}V){take}{delta_}{+ +}C)/{delta_}3 @ skip all but version markers {de{+ +}lta_}C{<-}({rho}{delta_}V){drop}{delta_}C {+ +} {delta_}C{<-}1{take}{delta_}XNUMS({neg}1{+ +}+{delta_}C{iota}''(''){take}{delta_}C @ version number in the argum{+ +}ent {delta_}N{<-}1{take}{delta_}XNUMS({neg}1+{delta_}A2AVER{io{+ +}ta}''(''){take}{delta_}A2AVER @ our version number {-{+ +}>}({delta_}C={delta_}N)/{delta_}3 @ done if versions {+ +}are indentical {->}({delta_}C>1.3)/{delta_}4 @ {+ +} warn of v1.3 incompatibility {delta_}OUT {delta_}TCNL,''{+ +}Warning: This transliteration was produced using an old'' {delta_{+ +}}OUT''version of APLASCII. Certain nested arrays may not be received'' {+ +} {delta_}OUT''correctly, possibly without producing any error message{+ +}.'' {->}{delta_}3 @ perhaps we{+ +} should quit instead... {delta_}4:{->}({delta_}C<{delta_}N)/{delta{+ +}_}5 @ warn if argument is newer {delta{+ +}_}OUT {delta_}TCNL,''Warning: This transliteration was produced using a n{+ +}ewer'' {delta_}OUT''version of APLASCII. There may be compatibilit{+ +}y problems.'' {delta_}OUT''You should obtain version '',({for{+ +}mat}{delta_}C),'' of APLASCII and rerun this job.'' {->}{delta_}3 {+ +} {delt{+ +}a_}5: @ arg is older, but not 1.3 {+ +} @ For now, we assume that future versions will be upward compatible{+ +} {->}{delta_}3 {+ +} @ {+ +} @ {del}: prefix -- execute a statement {+ +} {delta_}6:{->}(''{del}:''{or}.{/=}1{dr{+ +}op}3{take}{delta_}C)/{delta_}7 {+ +} {execute}3{drop}{delta_}C @ If err{+ +}or, execute {->}{delta_}3 to restart {->}{delta_}3 {+ +} @ {+ +} @ {del}. {+ +}prefix -- extract a variable definition {d{+ +}elta_}7:{->}(''{del}.''{or}.{/=}1{drop}3{take}{delta_}C)/{delta_}15 {+ +} @ jump if not a variable {delta_}N{<-}({neg}1+{del{+ +}ta_}C{iota}''{<-}''){take}{delta_}C {+ +} {delta_}V{<-}(1+{rho}{delta_}N){drop}{delta_}C {+ +} @ value portion of listing {delta_}G{<-}{d{+ +}elta_}N{<-}({delta_}N{/=}'' '')/{delta_}N{<-}3{drop}{delta_}N @ {+ +}the variable name (drop NL and {del}.) {delta_}V{<-}{delta_}GETVAL{+ +} {delta_}V @ the array value {+ +} {->}(0{/=}{rho}{delta_}ERR)/{delta_}13 {+ +} {->}(0={rho}{delta_}K)/{delta_}9 {+ +} @ If any unrecognized keywords, {->}(1={rho}{rho}{de{+ +}lta_}V)/{delta_}8 @ If non-vector, {+ +} {delta_}OUT {delta_}TCNL,''Unrecognized keywords in non-vector va{+ +}riable '',{delta_}N,'':'' {delta_}OUT {delta_}K {+ +} @ it''s a bad error {->}{delta_}14 {+ +} @ Else, a vector, {del{+ +}ta_}8:{delta_}OUT {delta_}TCNL,''Warning--unrecognized keywords in variabl{+ +}e '',{delta_}N,'':'' {delta_}OUT {delta_}K {+ +} @ just a warning this time, mister {delta_}9:{->}(''#''{/=}{+ +}1{take}{delta_}N)/{delta_}10 @ If this is a quad variable,{+ +} {delta_}G{<-}{delta_}N{<-}0 {delta_}QUADCASE {delta_}N {+ +} @ normalize the case {->}(0={delta_}QVARS {+ +}{delta_}MATIOTA {delta_}N)/{delta_}12 @ err if not available on t{+ +}his APL {->}({or}/{/=}{slashbar}{delta_}TOLOWER''#IO '',[.5]4{take}{{+ +}delta_}N)/{delta_}11 @ If the var is #IO, {->}(2{/=}{+ +}#NC''{delta_}QIO'')/{delta_}12 @ balk if we weren''t {+ +}called by LOADWS {delta_}G{<-}''{delta_}QIO'' @ {+ +} assign #IO value to surrogate {delta_}10:{delta_}T{<-}#EX {delta_{+ +}}G @ erase non-# first in case def''d as fn {->}({+ +}0{/=}#NC {delta_}G)/{delta_}12 @ jump if assignment will {+ +}likely fail {delta_}11:{execute}{delta_}G,''{<-}{delta_}V'' {+ +} @ define the var @ {first} {delta_{+ +}}G is usually the same as {delta_}N, except when {delta_}N is ''#IO'' {+ +} {->}{delta_}22 {+ +} {delta_}12:{delta_}H{<-}{delta_}N {+ +} @ remember the original name {execute}({delta{+ +}_}N{<-}{delta_}GENSYM''VAR''),''{<-}{delta_}V'' @ assign to surrog{+ +}ate {delta_}OUT {delta_}TCNL,''Unable to assign var{+ +}iable '',{delta_}H,''. Value stored in '',{delta_}N,''.'' {->}{delt{+ +}a_}22 {+ +} {delta_}13:{delta_}OUT {delta_}TCNL,''Unable to extract value of varia{+ +}ble '',{delta_}N,'' ('',{delta_}ERR,'').'' {delta_}14:{execute}({del{+ +}ta_}N{<-}{delta_}GENSYM''VAR''),''{<-}{delta_}R'' @ save the untransl{+ +}iterated value {delta_}OUT''Transfer form stored in variable ''{+ +},{delta_}N,''.'' {->}{delta_}22 {+ +} @ {+ +} @ {del} {+ +}prefix -- extract a function definition: {{+ +}delta_}15:{delta_}C{<-}(2+2{times}''[''={delta_}C[2]){drop}{delta_}C {+ +}@ drop initial newline and {del} or [0] {->}(''APLPLUS''^.=7{t{+ +}ake}{delta_}APLVER)/{delta_}17 @ APL*PLUS tolerates either case {+ +} {->}(''APL68K''{or}.{/=}6{take}{delta_}APLVER)/{delta_}16 @ In {+ +}APL.68000... {->}({delta_}LEVEL>1)/{delta_}17 {+ +} @ Level II tolerates either case {delta_}16:{de{+ +}lta_}C{<-}0 {delta_}QUADCASE {delta_}C @ convert quad names to{+ +} the primary case {delta_}17:{delta_}C{<-}0 {delta_}EJCASE {delta_}C {+ +} @ convert E/J in nums to primary case {delta_}H{<-}({ne{+ +}g}1+{delta_}C{iota}{delta_}TCNL){take}{delta_}C @ header line{+ +} {delta_}C{<-}({rho}{delta_}H){drop}{delta_{+ +}}C @ rest of fn {delt{+ +}a_}C{<-}{delta_}VTOM {delta_}C @ as a matrix {+ +} {->}(0{epsilon}{rho}{delta_}C)/{delta_}19 {+ +} @ jump if body is empty {delta_}W{<-}1++/^{+ +}\{delta_}C{/=}'']'' @ width of line number on each line {+ +} {delta_}W{<-}{delta_}W{times}{delta_}C[;1]=''['' @ {+ +} zero width for lines w/o numbers {delta_}C{<-}(-{delta_}W){rota{+ +}te}({rho}{delta_}C){take}{delta_}W{rotate}(({rho}{delta_}C)+0,{max}/{delta{+ +}_}W){take}{delta_}C @ remove the line numbers {delta_}C{<-{+ +}}{delta_}DLTB {delta_}C @ delete leading and trailing{+ +} blank cols {->}(0{epsilon}{rho}{delta_}C)/{delta_}19 {+ +} @ careful--may be empty now {->}({or}/({delta_}C[;1]={+ +}'' '')^{delta_}C{or}.{/=}'' '')/{delta_}18@ If no exdents, {+ +} {delta_}C{<-}'' '',{delta_}C @ i{+ +}ndent all lines {delta_}18:{->}(''APL68K''{or}.{/=}6{+ +}{take}{delta_}APLVER)/{delta_}19@ If on APL.68000, {+ +} {delta_}C[({delta_}C^.='' '')/{iota}1{take}{rho}{delta_}C;1]{<-}''@'{+ +}' @ make blank line be comments @ {first} If we don''t{+ +} do this, APL.68000 deletes the blank lines {delta_}19:{{+ +}delta_}C{<-}('' '',{delta_}DLTB {delta_}H){delta_}OVER {delta_}C @ res{+ +}tore the header {delta_}W{<-}{delta_}FNNAME {delta{+ +}_}H @ name of fcn (or operator) {delta{+ +}_}T{<-}#EX {delta_}W @ erase first, in case defined{+ +} as var {->}(0{/=}#NC {delta_}W)/{delta_}20 @ jump{+ +} if it wouldn''t erase {delta_}N{<-}#FX {delta_}C {+ +} @ define as fn {->}(0{/=}1{t{+ +}ake}0{rho}{delta_}N)/{delta_}21 @ If #FX failed, {+ +} {delta_}20:{delta_}N{<-}{delta_}GENSYM''CR'' {+ +} @ available name {execute}{delta_}N,''{<-{+ +}}{delta_}C'' @ save the #CR {+ +} {delta_}OUT {delta_}TCNL,''Unable to define '',{delta_}W,''. #CR s{+ +}tored in variable '',{delta_}N,''.'' {->}(0={rho}{delta_}K)/{delta{+ +}_}22 {del{+ +}ta_}OUT''And, by the way, it contains the following unrecognized keywords:{+ +}'' {delta_}OUT {delta_}K {+ +} {->}{delta_}22 {+ +} {delta_}21:{->}(0={rho}{delta_}K)/{+ +}{delta_}22 {{+ +}delta_}OUT {delta_}TCNL,''Warning--unrecognized keywords in '',{delta_}W,'{+ +}':'' {delta_}OUT {delta_}K {+ +} @ {+ +} {delta_}22:{delta_}Z{<-}{{+ +}delta_}Z {delta_}OVER {delta_}N @ remember what we defined {+ +} {->}{delta_}3 @ Endloop {+ +} @ {+ +} ASCII2APL @ access{+ +}ed thru {execute} @ Copyright (c) 1994-95 Ji{+ +}m Weigang @ APLASCII.Update vers{+ +}ion 1.4 (1997.10.29) ' {del}: #{<-}{delta_}TCNL,'Now execute:',{delta_}TCNL,' #FX CR',{delta_}TCNL,' )ERASE CR',{delta_}TCNL,' )SAVE',{delta_}TCNL - fin -