summaryrefslogtreecommitdiff
path: root/web/maple
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/maple
Initial commit
Diffstat (limited to 'web/maple')
-rw-r--r--web/maple/mapleweb/Makefile144
-rw-r--r--web/maple/mapleweb/maple.spider196
-rw-r--r--web/maple/mapleweb/tangle.ch164
-rw-r--r--web/maple/mapleweb/weave.ch106
4 files changed, 610 insertions, 0 deletions
diff --git a/web/maple/mapleweb/Makefile b/web/maple/mapleweb/Makefile
new file mode 100644
index 0000000000..c9edbfdfb5
--- /dev/null
+++ b/web/maple/mapleweb/Makefile
@@ -0,0 +1,144 @@
+# Copyright 1989 by Norman Ramsey, Odyssey Research Associates.
+# To be used for research purposes only.
+# For more information, see file COPYRIGHT in the parent directory.
+
+HOME=/users/redusers# # Make no longer inherits environment vars
+
+THETANGLE=tangle
+THEWEAVE=weave
+SPIDER=any.spider
+#
+DVI=dvi
+CFLAGS=-DDEBUG -g -DSTAT
+
+# CPUTYPE is a grim hack that attempts to solve the problem of multiple
+# cpus sharing a file system. In my environment I have to have different
+# copies of object and executable for vax, sun3, next, iris, and other
+# cpu types. If you will be using Spidery WEB in a homogenous processor
+# environment, you can just set CPUTYPE to a constant, or eliminate it
+# entirely.
+#
+# In my environment, the 'cputype' program returns a string that
+# describes the current processor. That means that the easiest thing
+# for you to do is to define a 'cputype' program that does something
+# sensible. A shell script that says 'echo "vax"' is fine.
+
+CPUTYPE=`cputype`
+
+# Change the following three directories to match your installation
+#
+# the odd placement of # is to prevent any trailing spaces from slipping in
+
+WEBROOT=$(HOME)/spider# # root of the WEB source distribution
+DEST=$(HOME)/bin# # place where the executables go
+MACROS=$(HOME)/tex/inputs# # place where the macros go
+
+MASTER=$(WEBROOT)/master# # master source directory
+OBDIR=$(MASTER)/$(CPUTYPE)# #common object files
+
+TANGLESRC=tangle
+CTANGLE=ceetangle -I$(MASTER)
+CWEAVE=ceeweave -I$(MASTER)
+AWKTANGLE=awktangle -I$(MASTER)
+COMMONOBJS=$(OBDIR)/common.o $(OBDIR)/pathopen.o
+COMMONC=$(MASTER)/common.c $(MASTER)/pathopen.c
+COMMONSRC=$(COMMONC) $(MASTER)/spider.awk
+
+
+# Our purpose is to make tangle and weave
+
+web: tangle weave
+
+tangle: mktangle
+
+mktangle: $(COMMONOBJS) $(TANGLESRC).o
+ $(CC) $(CFLAGS) -o $(DEST)/$(THETANGLE) $(COMMONOBJS) $(TANGLESRC).o
+
+weave: $(COMMONOBJS) weave.o
+ $(CC) $(CFLAGS) -o $(DEST)/$(THEWEAVE) $(COMMONOBJS) weave.o
+
+source: $(TANGLESRC).c $(COMMONSRC) # make tangle.c and common src, then clean
+ if [ -f WebMakefile ]; then exit 1; fi # don't clean the master!
+ if [ -f spiderman.tex ]; then exit 1; fi # don't clean the manual
+ -rm -f tangle.web weave.* common.* # remove links that may be obsolete
+ -rm -f *.unsorted *.list grammar.web outtoks.web scraps.web
+ -rm -f cycle.test spider.slog
+ -rm -f *.o *.tex *.toc *.dvi *.log *.makelog *~ *.wlog *.printlog
+
+# Here is how we make the common stuff
+
+$(MASTER)/common.c: $(MASTER)/common.web # no change file
+ $(CTANGLE) $(MASTER)/common
+
+$(OBDIR)/common.o: $(MASTER)/common.c
+ $(CC) $(CFLAGS) -c $(MASTER)/common.c
+ mv common.o $(OBDIR)
+
+$(MASTER)/pathopen.c: $(MASTER)/pathopen.web # no change file
+ $(CTANGLE) $(MASTER)/pathopen
+ mv pathopen.h $(MASTER)
+
+$(OBDIR)/pathopen.o: $(MASTER)/pathopen.c
+ $(CC) $(CFLAGS) -c $(MASTER)/pathopen.c
+ mv pathopen.o $(OBDIR)
+
+$(OBDIR):
+ if /bin/test ! -d $(OBDIR) ; then mkdir $(OBDIR) ; fi
+
+## Now we make the tangle and weave source locally
+
+$(TANGLESRC).c: $(MASTER)/$(TANGLESRC).web $(MASTER)/common.h grammar.web tangle.ch
+ -/bin/rm -f $(TANGLESRC).web
+ ln $(MASTER)/$(TANGLESRC).web $(TANGLESRC).web
+ $(CTANGLE) $(TANGLESRC) tangle.ch
+
+weave.c: $(MASTER)/weave.web $(MASTER)/common.h grammar.web weave.ch
+# van vorige lijn: rweave.ch
+ -/bin/rm -f weave.web
+ ln $(MASTER)/weave.web weave.web
+ $(CTANGLE) weave weave.ch
+
+## Here's where we run SPIDER to create the source
+
+grammar.web: $(MASTER)/cycle.awk $(MASTER)/spider.awk $(SPIDER)
+ echo "date" `date` | cat - $(SPIDER) | awk -f $(MASTER)/spider.awk
+ cat $(MASTER)/transcheck.list trans_keys.unsorted | awk -f $(MASTER)/transcheck.awk
+ awk -f $(MASTER)/cycle.awk < cycle.test
+ sort *.unsorted | awk -f $(MASTER)/nodups.awk
+ mv *web.tex $(MACROS)
+
+## We might have to make spider first.
+
+$(MASTER)/spider.awk: $(MASTER)/spider.web
+ $(AWKTANGLE) $(MASTER)/spider
+ mv cycle.awk nodups.awk transcheck.awk $(MASTER)
+ rm junk.list
+
+
+# $(MASTER)/cycle.awk: $(MASTER)/cycle.web # making spider also makes cycle
+# $(AWKTANGLE) $(MASTER)/cycle
+
+
+# This cleanup applies to every language
+
+clean:
+ if [ -f WebMakefile ]; then exit 1; fi # don't clean the master!
+ if [ -f spiderman.tex ]; then exit 1; fi # don't clean the manual
+ -rm -f tangle.* weave.* common.* # remove links that may be obsolete
+ -rm -f *.unsorted *.list grammar.web outtoks.web scraps.web
+ -rm -f cycle.test spider.slog
+ -rm -f *.c *.o *.tex *.toc *.dvi *.log *.makelog *~ *.wlog *.printlog
+
+
+
+# booting the new distribution
+boot:
+ cd ../master; rm -f *.o; for i in $(COMMONC); do \
+ $(CC) $(CFLAGS) -c $$i; \
+ mv *.o $(OBDIR) ; \
+ done; cd ../c
+ $(CC) $(CFLAGS) -c $(TANGLESRC).c; \
+ $(CC) $(CFLAGS) -o $(DEST)/$(THETANGLE) $(COMMONOBJS) $(TANGLESRC).o
+
+
+
diff --git a/web/maple/mapleweb/maple.spider b/web/maple/mapleweb/maple.spider
new file mode 100644
index 0000000000..c5406aabd0
--- /dev/null
+++ b/web/maple/mapleweb/maple.spider
@@ -0,0 +1,196 @@
+language MAPLE extension mpl
+
+module definition stmt use stmt
+token newline category ignore_scrap translation <>
+
+comment begin <"#"> end newline
+
+default translation <*> mathness no
+
+line begin <"#line"> end <>
+
+token pseudo_semi category terminator translation <"\\rx">
+
+token identifier category ident
+token number category numbr
+token { category slopen translation <"\\{">
+token } category slclose translation <"\\}">
+token [ category slopen tangleto <space-"\[">
+token ] category slclose tangleto <"\]"-space>
+token ( category open
+token ) category close
+
+#what to do with ' and ` and "??
+#token ` category backquote
+
+token ' category math tangleto <space-"'">
+token . category point
+token ; category terminator translation <";"-break_space>
+token : category terminator translation <":"-break_space>
+token , category comma translation <","-opt-1>
+token \ category backslash translation <"\\backslash">
+#tijdelijk: van vorige regel: tangleto <"\\">
+token := category assignment translation <":=">
+token $ category binop translation <"\\,\\$\\,">
+#token .. category binop translation <"..">
+token * category binop
+token ^ category binop
+token / category binop
+token <> category binop translation <"\\NEQ"> tangleto <"<>">
+token <= category binop translation <"\\leq">
+token >= category binop translation <"\\geq">
+token = category binop
+token < category binop
+token > category binop
+token ! category unop
+token + category unorbinop
+token - category unorbinop
+
+#ilk definitions
+ilk forstart_like category forstart
+ilk forbodystart_like category forbodystart
+ilk forbodyend_like category forbodyend
+ilk ifbegin_like category ifbegin
+ilk ifthen_like category ifthen
+ilk elif_like category elif
+ilk ifbody_like category ifbody
+ilk ifend_like category ifend
+ilk procedure_like category procedure
+ilk procextra_like category procextra
+ilk procend_like category procend
+ilk return_like category return
+ilk ident_like category ident
+
+default translation <"\\"-space-*-"\\"-space>
+
+ilk binop_like category binop
+
+reserved proc ilk procedure_like
+reserved end ilk procend_like
+reserved local ilk procextra_like
+reserved option ilk procextra_like
+reserved minus ilk binop_like
+
+reserved for ilk forstart_like
+reserved while ilk forstart_like
+reserved to ilk forstart_like
+reserved in ilk forstart_like
+reserved from ilk forstart_like
+reserved do ilk forbodystart_like
+reserved od ilk forbodyend_like
+reserved if ilk ifbegin_like
+reserved then ilk ifthen_like
+reserved elif ilk elif_like
+reserved else ilk ifbody_like
+reserved fi ilk ifend_like
+reserved RETURN ilk return_like
+reserved break ilk ident_like
+reserved next ilk ident_like
+#token category
+
+#production rules
+#? ignore_scrap --> #1
+
+#handling statements;
+<"$"> math <"$"> terminator --> stmt
+stmt <space> stmt --> stmt
+stmt terminator --> stmt
+ignore_scrap --> terminator
+terminator --> stmt
+
+#handling comments
+#comment newline --> newline
+#comment ? --> comment
+
+#handling idents and math etc.
+<force> return --> math
+ident --> math
+numbr --> math
+(unop|unorbinop|binop) math --> math
+math (unop|unorbinop|binop) --> math
+math math --> math
+math comma --> math
+math [ point point ] --> math binop
+math point --> math
+math assignment --> math
+<"$"> math <"$"> <space> terminator --> stmt
+
+
+#handlig forloops
+forstart <space> <"$"> math <"$"> <space> --> forstart
+forstart forstart --> forstart
+forstart <space> forbodystart <force-indent> --> forbodystart
+forbodystart stmt --> forbodystart
+<force> forbodystart <outdent-force> forbodyend terminator <force> --> stmt
+<force> forbodystart <outdent-force> forbodyend <force> --> stmt
+<force> forbodystart <space> <"$"> math <"$"> <outdent-force> forbodyend terminator <force> --> stmt
+<force> forbodystart <space> <"$"> math <"$"> <outdent> <force> forbodyend <force> --> stmt
+
+
+#handling ifstatements
+<force> ifbegin <space> <"$"> math <"$"> <space> ifthen <force-indent> --> ifbegin
+ifbegin stmt --> ifbegin
+ifbegin <outdent-force> ifend terminator <force> --> stmt
+ifbegin <outdent-force> ifend <force> --> stmt
+ifbegin <"$"> math <"$"> <outdent-force> ifend terminator <force> --> stmt
+ifbegin <"$"> math <"$"> <outdent-force> ifend <force> --> stmt
+
+ifbegin <outdent-force> ifbody <space> <indent> --> ifbegin
+ifbegin <space> <"$"> math <"$"> <outdent-force> ifbody <space> <indent> --> ifbegin
+
+elif <space> <"$"> math <"$"> <space> ifthen <force-indent> --> elif
+elif stmt --> elif
+elif <space> <"$"> math <"$"> <outdent-force> elif --> elif
+elif <outdent-force> elif --> elif
+elif <outdent-force> ifbody <space> <indent> --> elif
+elif <"$"> math <"$"> <outdent-force> ifbody <space> <indent> --> elif
+elif <"$"> math <"$"> <outdent-force> ifend terminator <force> --> elifend
+elif <"$"> math <"$"> <outdent-force> ifend <force> --> elifend
+elif <outdent-force> ifend terminator <force> --> elifend
+elif <outdent-force> ifend <force> --> elifend
+
+ifbegin <outdent-force> elifend --> stmt
+ifbegin <"$"> math <"$"> <outdent-force> elifend --> stmt
+
+#handling procedures
+
+<"$"> math <"$"> <force> <indent> procedure <"$"> math <"$"> <force> --> procedure
+procedure <force> procextra <space> stmt <force> --> procedure
+procedure <indent> stmt --> procbody
+procbody stmt --> procbody
+
+procbody <outdent> <force> procend terminator <big_force-outdent> --> stmt
+procbody <"$"> math <"$"> <outdent> <force> procend terminator <big_force-outdent> --> stmt
+
+procbody <outdent> <force> procend <big_force-outdent> --> stmt
+procbody <"$"> math <"$"> <outdent> <force> procend <big_force-outdent> --> stmt
+procedure <space> <indent> <"$"> math <"$"> <force> <outdent> procend terminator <big_force-outdent> --> stmt
+procedure <space> <indent> <"$"> math <"$"> <force> <outdent> procend <big_force-outdent> --> stmt
+
+#handling sets and lists
+open <"\\,"> close --> math
+open <"\\,"> math <"\\,"> close --> math
+slopen <"\\,"> slclose --> math
+slopen <"\\,"> math <"\\,"> slclose --> math
+
+#handling backslash
+math backslash math --> math
+backslash newline --> newline
+backslash backslash --> math
+backslash --> math
+
+#handling backquote
+#changefile makes '`' reading as string!
+
+
+macros begin
+\def\commentbegin{\#}
+\def\commentend{}
+\def\NEQ{\ne}
+\def\LL{\ll\,}
+\def\RR{\,\gg}
+\def\PS{\joinrel{+\equiv}}
+\let\rx\relax
+
+macros end
+
diff --git a/web/maple/mapleweb/tangle.ch b/web/maple/mapleweb/tangle.ch
new file mode 100644
index 0000000000..2e309c7548
--- /dev/null
+++ b/web/maple/mapleweb/tangle.ch
@@ -0,0 +1,164 @@
+Maple strings start with '`'
+tangle.web line 1074
+
+@x
+ if (isdigit(c) || c=='\\' || c=='.') @<Get a constant@>@;/*spider*/
+ else if (isalpha(c) || c=='_' || c=='$') @<Get an identifier@>@;/*spider*/
+ else if (c=='\'' || c=='\"') @<Get a string@>@;/*spider*/
+@y
+ if (isdigit(c) || c=='.') @<Get a constant@>@;/*spider*/
+ else if (isalpha(c) || c=='_' || c=='\\') @<Get an identifier@>@;/*spider*/
+ else if (c=='`' ) @<Get a string@>@;/*spider*/
+@z
+
+@x
+@ @<Get an identifier@>= {/*spider*/
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || *loc=='_');
+ if (*loc=='$') while (isdigit(*++loc)||*loc=='$');
+ /* make room for \$\$ and \$nnn suffixes */
+ id_loc=loc; return(identifier);
+}
+@y
+@ @<Get an identifier@>= {/*spider*/
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || *loc=='_' || *loc=='\\');
+ id_loc=loc; return(identifier);
+}
+@z
+
+
+Maple allows e.g. 1234\4567 for 'better' readability
+tangle.web line 1092
+@x
+@ @<Get a constant@>= {/*spider*/
+ id_first=loc-1;
+ if (*id_first=='.' && !isdigit(*loc)) goto mistake; /* not a constant */
+ if (*id_first=='\\') while (isdigit(*loc)) loc++; /* octal constant */
+ else {
+ if (*id_first=='0') {
+ if (*loc=='x' || *loc=='X') { /* hex constant */
+ loc++; while (isxdigit(*loc)) loc++; goto found;
+ }
+ }
+ while (isdigit(*loc)) loc++;
+ if (*loc=='.') {
+ loc++;
+ while (isdigit(*loc)) loc++;
+ }
+ if (*loc=='e' || *loc=='E') { /* float constant */
+ if (*++loc=='+' || *loc=='-') loc++;
+ while (isdigit(*loc)) loc++;
+ }
+ }
+ found:
+ id_loc=loc;
+ return(constant);
+}
+@y
+@ @<Get a constant@>= {/*spider*/
+ id_first=loc-1;
+ if (*id_first=='.' && !isdigit(*loc)) goto mistake; /* not a constant */
+ if (*id_first=='\\') while (isdigit(*loc)) loc++; /* octal constant */
+ else {
+ if (*id_first=='0') {
+ if (*loc=='x' || *loc=='X') { /* hex constant */
+ loc++; while (isxdigit(*loc)) loc++; goto found;
+ }
+ }
+ while (isdigit(*loc)) loc++;
+ if (*loc=='.' || *loc=='\\') {
+ loc++;
+ while (isdigit(*loc)) loc++;
+ }
+ if (*loc=='e' || *loc=='E') { /* float constant */
+ if (*++loc=='+' || *loc=='-') loc++;
+ while (isdigit(*loc)) loc++;
+ }
+ }
+ found:
+ id_loc=loc;
+ return(constant);
+}
+@z
+
+tangle.web line 1122
+@x
+@<Get a string@>= {/*spider*/
+ ASCII delim = c; /* what started the string */
+@#
+/* if it's not a single-character literal, it's a tick mark or an |at_sign| */
+ if (delim=='\'' && (loc+1>=limit ||
+ (*loc != '\\' && *loc!=at_sign && loc[1]!='\'') ||
+ (*loc=='\\' && (loc+2>=limit||loc[2]!='\'')) ||
+ (*loc==at_sign &&
+ (loc+2>=limit||loc[1]!=at_sign||loc[2]!='\''))
+ )) goto mistake;
+ id_first = mod_text+1;
+ id_loc = mod_text; *++id_loc=delim;
+ while (1) {
+ if (loc>=limit) {
+ if(*(limit-1)!='\\') {
+ err_print("! String didn't end"); loc=limit; break;
+@.String didn't end@>
+ }
+ if(get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer; break;
+@.Input ended in middle of string@>
+ }
+ else if (++id_loc<=mod_text_end) *id_loc=@`\n'; /* will print as
+ \.{"\\\\\\n"} */
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ break;
+ }
+ if (c=='\\') {
+ if (loc>=limit) continue;
+ if (++id_loc<=mod_text_end) *id_loc = '\\';
+ c=*loc++;
+ }
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ }
+ if (id_loc>=mod_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ ASCII_write(mod_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+@y
+@<Get a string@>= {/*spider*/
+ ASCII delim = c; /* what started the string */
+@#
+ id_first = mod_text+1;
+ id_loc = mod_text; *++id_loc=delim;
+ while (1) {
+ if (loc>=limit) {
+ err_print("! String didn't end"); loc=limit;
+@.String didn't end@>
+ if (get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer;
+@.Input ended in middle of string@>
+ }
+ break;
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ if (*loc==delim) loc++;
+ else break;
+ }
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ }
+ if (id_loc>=mod_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ ASCII_write(mod_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+@z \ No newline at end of file
diff --git a/web/maple/mapleweb/weave.ch b/web/maple/mapleweb/weave.ch
new file mode 100644
index 0000000000..3036670c6c
--- /dev/null
+++ b/web/maple/mapleweb/weave.ch
@@ -0,0 +1,106 @@
+ line 547 of weave.web
+@x
+ else if (c=='\'' || c=='"') @<Get a string@>@;/*spider*/
+@y
+ else if (c=='`') @<Get a string@>@;/*spider*/
+@z
+
+ line 608 of weave.web
+@x
+@ \cee\ strings and character constants, delimited by double and single
+quotes, respectively, can contain newlines or instances of their own
+delimiters if they are protected by a backslash. We follow this
+convention, but do not allow the string to be longer than |longest_name|.
+
+@<Get a string@>= {/*spider*/
+ ASCII delim = c; /* what started the string */
+ id_first = mod_text+1;
+ id_loc = mod_text;
+ if (delim=='`' && *(loc-2)==at_sign) {
+ /* make string begin with |"@@`"| */
+ *++id_loc=at_sign;
+ *++id_loc=at_sign;
+ }
+ /* this is hack for ascii constant */
+@#
+/* if it's not a single-character literal, it's a tick mark or an |at_sign| */
+ if ((delim=='\'' || delim == '`') &&
+ (loc+1>=limit ||
+ (*loc != '\\' && *loc!=at_sign && loc[1]!='\'') ||
+ (*loc=='\\' && (loc+2>=limit||loc[2]!='\'')) ||
+ (*loc==at_sign &&
+ (loc+2>=limit||loc[1]!=at_sign||loc[2]!='\''))
+ )
+ ) goto mistake;
+ *++id_loc=delim;
+ if (delim=='`') delim='\''; /* for |ascii_constant|s */
+ while (1) {
+ if (loc>=limit) {
+ if(*(limit-1)!='\\') {
+ err_print("! String didn't end"); loc=limit; break;
+@.String didn't end@>
+ }
+ if(get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer; break;
+@.Input ended in middle of string@>
+ }
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ break;
+ }
+ if (c=='\\') if (loc>=limit) continue;
+ else if (++id_loc<=mod_text_end) {
+ *id_loc = '\\'; c=*loc++;
+ }
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ }
+ if (id_loc>=mod_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ ASCII_write(mod_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+@y
+
+@ \cee\ strings are delimited by backquotes and must be restricted
+to one line. A backquote in strings must be doubled and we allow no
+string to be longer than |longest_name|.
+@<Get a string@>= {/*spider*/
+ ASCII delim = c; /* what started the string */
+@#
+ id_first = mod_text+1;
+ id_loc = mod_text; *++id_loc=delim;
+ while (1) {
+ if (loc>=limit) {
+ err_print("! String didn't end"); loc=limit;
+@.String didn't end@>
+ if (get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer;
+@.Input ended in middle of string@>
+ }
+ break;
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ if (*loc==delim) loc++;
+ else break;
+ }
+ if (++id_loc<=mod_text_end) *id_loc=c;
+ }
+ if (id_loc>=mod_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ ASCII_write(mod_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+
+@z
+
+