Commit f923cf75 authored by david_v's avatar david_v
Browse files

2004-02-13 Valentin David <valentin@lrde.epita.fr>

	* src/disamb/disambiguate/TypeDefinition.str,
	* src/disamb/disambiguate/TypeDeclarator.str,
	* src/disamb/disambiguate/TypeAmbiguityCut.str,
	* src/disamb/disambiguate/Makefile.am,
	* src/disamb/disambiguate/Lookup.str,
	* src/disamb/disambiguate/ClassOrNamespaceTraverse.str,
	* src/disamb/disambiguate/CheckClassName.str:
	Treat typdefs as alias.

	* src/disamb/disambiguate/GetKey.str,
	* src/disamb/disambiguate/GetKey.meta: New.

	* test/disambiguate/alias-01.cc,
	* test/disambiguate/alias-01.detcc: New.

	* test/disambiguate/Makefile.am: Update.
parent 9f4e9c63
2004-02-13 Valentin David <valentin@lrde.epita.fr>
* src/disamb/disambiguate/TypeDefinition.str,
* src/disamb/disambiguate/TypeDeclarator.str,
* src/disamb/disambiguate/TypeAmbiguityCut.str,
* src/disamb/disambiguate/Makefile.am,
* src/disamb/disambiguate/Lookup.str,
* src/disamb/disambiguate/ClassOrNamespaceTraverse.str,
* src/disamb/disambiguate/CheckClassName.str:
Treat typdefs as alias.
* src/disamb/disambiguate/GetKey.str,
* src/disamb/disambiguate/GetKey.meta: New.
* test/disambiguate/alias-01.cc,
* test/disambiguate/alias-01.detcc: New.
* test/disambiguate/Makefile.am: Update.
* src/strategocxx/Makefile.am,
* test/expressions/Makefile.am (CLEANFILES):
Delete trailing files.
......
;; -*- Prcs -*-
(Created-By-Prcs-Version 1 3 2)
(Project-Description "Meta/SDF Grammar for C++")
(Project-Version meta-c++-grammar 0 150)
(Parent-Version meta-c++-grammar 0 149)
(Project-Version meta-c++-grammar 0 151)
(Parent-Version meta-c++-grammar 0 150)
(New-Version-Log "")
(Version-Log "2004-02-13 Valentin David <valentin@lrde.epita.fr>
* src/strategocxx/Makefile.am,
* test/expressions/Makefile.am (CLEANFILES):
Delete trailing files.")
* src/disamb/disambiguate/TypeDefinition.str,
* src/disamb/disambiguate/TypeDeclarator.str,
* src/disamb/disambiguate/TypeAmbiguityCut.str,
* src/disamb/disambiguate/Makefile.am,
* src/disamb/disambiguate/Lookup.str,
* src/disamb/disambiguate/ClassOrNamespaceTraverse.str,
* src/disamb/disambiguate/CheckClassName.str:
Treat typdefs as alias.
(Checkin-Time "Fri, 13 Feb 2004 16:30:05 +0100")
* src/disamb/disambiguate/GetKey.str,
* src/disamb/disambiguate/GetKey.meta: New.
* test/disambiguate/alias-01.cc,
* test/disambiguate/alias-01.detcc: New.
* test/disambiguate/Makefile.am: Update.")
(Checkin-Time "Fri, 13 Feb 2004 19:50:28 +0100")
(Checkin-Login david_v)
(Populate-Ignore
(
......@@ -68,11 +81,16 @@
"^src/disamb/resolve/afcxx-resolve$"
"^src/disamb/specifier/afcxx-specifier-ast$"
"^src/disamb/specifier/afcxx-specifier$"
"^src/disamb/disambiguate/afcxx-disambiguate-ast$"
"^src/disamb/disambiguate/afcxx-disambiguate$"
"^src/disamb/ambdown/ambdown$"
"^src/disamb/namespace/afcxx-namespace-ast$"
"^src/disamb/namespace/afcxx-namespace$"
;; XT, Meta && Stratego
"\\.\\(tbl\\|eqs\\|def\\|ppdef\\|pp\\|pp\\.af\\|dep\\|tree\\|c\\)$"
"^src/sig/.*\\.str$"
"^src/sig/.*\\.rtree$"
"\\.rtree$"
"^src/sdf/.*\\.sdf$"
"^src/strategocxx/StrategoCxxGen.sdf$"
"^src/deterministic/DetCxx.sdf$"
......@@ -92,6 +110,10 @@
"^test/.*[^t][^e][^s][^t]\\.test$"
"^test/.*/dirs$"
"^test/.*/defs$"
"\\.visamb$"
"\\.astcc"
"\\.diff$"
"\\.ptcc$"
"\\.\\(bak\\|new\\|old\\|rej\\|orig\\|works\\|save\\)$"
"CVS/"
......@@ -114,7 +136,7 @@
)
(Project-Keywords)
(Files
(ChangeLog (meta-c++-grammar/0_ChangeLog 1.146 600))
(ChangeLog (meta-c++-grammar/0_ChangeLog 1.147 600))
(Makefile.am (meta-c++-grammar/f/34_Makefile.a 1.13 644))
(README (meta-c++-grammar/g/37_README 1.7 600))
(config/Makefile.am (meta-c++-grammar/f/40_Makefile.a 1.5 644))
......@@ -524,7 +546,7 @@
(test/disambiguate/class-02.detcc (meta-c++-grammar/j/16_class-02.d 1.2 644))
(test/disambiguate/class-01.detcc (meta-c++-grammar/j/17_class-01.d 1.1 644))
(test/disambiguate/test.test (meta-c++-grammar/j/18_test.test 1.4 750))
(test/disambiguate/Makefile.am (meta-c++-grammar/j/19_Makefile.a 1.9 640))
(test/disambiguate/Makefile.am (meta-c++-grammar/j/19_Makefile.a 1.10 640))
(test/expressions/Makefile.am (meta-c++-grammar/j/20_Makefile.a 1.7 640))
(test/expressions/test.test (meta-c++-grammar/j/21_test.test 1.2 750))
(test/g++/Makefile.am (meta-c++-grammar/j/22_Makefile.a 1.1 644))
......@@ -557,10 +579,10 @@
(src/disamb/disambiguate/VariableDeclaratorCandidate.str (meta-c++-grammar/j/49_VariableDe 1.3 644))
(src/disamb/disambiguate/VariableDeclarator.str (meta-c++-grammar/j/50_VariableDe 1.3 644))
(src/disamb/disambiguate/TypeDefinitionCandidate.str (meta-c++-grammar/j/51_TypeDefini 1.3 644))
(src/disamb/disambiguate/TypeDefinition.str (meta-c++-grammar/k/0_TypeDefini 1.4 644))
(src/disamb/disambiguate/TypeDefinition.str (meta-c++-grammar/k/0_TypeDefini 1.5 644))
(src/disamb/disambiguate/TypeDeclaratorCandidate.str (meta-c++-grammar/k/1_TypeDeclar 1.3 644))
(src/disamb/disambiguate/TypeDeclarator.str (meta-c++-grammar/k/2_TypeDeclar 1.3 644))
(src/disamb/disambiguate/TypeAmbiguityCut.str (meta-c++-grammar/k/3_TypeAmbigu 1.2 644))
(src/disamb/disambiguate/TypeDeclarator.str (meta-c++-grammar/k/2_TypeDeclar 1.4 644))
(src/disamb/disambiguate/TypeAmbiguityCut.str (meta-c++-grammar/k/3_TypeAmbigu 1.3 644))
(src/disamb/disambiguate/TypeAmbiguityCandidate.str (meta-c++-grammar/k/4_TypeAmbigu 1.3 644))
(src/disamb/disambiguate/TypeAmbiguity.str (meta-c++-grammar/k/5_TypeAmbigu 1.3 644))
(src/disamb/disambiguate/TemplateTraverseCandidate.str (meta-c++-grammar/k/6_TemplateTr 1.3 644))
......@@ -581,9 +603,9 @@
(src/disamb/disambiguate/NamespaceTraverse.str (meta-c++-grammar/k/21_NamespaceT 1.3 644))
(src/disamb/disambiguate/NamespaceDefinitionCandidate.str (meta-c++-grammar/k/22_NamespaceD 1.3 644))
(src/disamb/disambiguate/NamespaceDefinition.str (meta-c++-grammar/k/23_NamespaceD 1.4 644))
(src/disamb/disambiguate/Makefile.am (meta-c++-grammar/k/24_Makefile.a 1.6 640))
(src/disamb/disambiguate/Makefile.am (meta-c++-grammar/k/24_Makefile.a 1.7 640))
(src/disamb/disambiguate/afcxx-disambiguate.str (meta-c++-grammar/k/25_afcxx-disa 1.4 644))
(src/disamb/disambiguate/Lookup.str (meta-c++-grammar/k/26_Lookup.str 1.4 644))
(src/disamb/disambiguate/Lookup.str (meta-c++-grammar/k/26_Lookup.str 1.5 644))
(src/disamb/disambiguate/LocalOrGlobal.str (meta-c++-grammar/k/27_LocalOrGlo 1.3 644))
(src/disamb/disambiguate/Kinds.str (meta-c++-grammar/k/28_Kinds.str 1.3 644))
(src/disamb/disambiguate/Keys.str (meta-c++-grammar/k/29_Keys.str 1.3 644))
......@@ -592,7 +614,7 @@
(src/disamb/disambiguate/CompoundStatementCandidate.str (meta-c++-grammar/k/32_CompoundSt 1.3 644))
(src/disamb/disambiguate/CompoundStatement.str (meta-c++-grammar/k/33_CompoundSt 1.3 644))
(src/disamb/disambiguate/ClassTraverse.str (meta-c++-grammar/k/34_ClassTrave 1.4 644))
(src/disamb/disambiguate/ClassOrNamespaceTraverse.str (meta-c++-grammar/k/35_ClassOrNam 1.4 644))
(src/disamb/disambiguate/ClassOrNamespaceTraverse.str (meta-c++-grammar/k/35_ClassOrNam 1.5 644))
(src/disamb/disambiguate/ClassOrNamespaceAmbiguityCut.str (meta-c++-grammar/k/36_ClassOrNam 1.2 644))
(src/disamb/disambiguate/ClassOrNamespaceAmbiguityCandidate.str (meta-c++-grammar/k/37_ClassOrNam 1.3 644))
(src/disamb/disambiguate/ClassOrNamespaceAmbiguity.str (meta-c++-grammar/k/38_ClassOrNam 1.3 644))
......@@ -601,7 +623,7 @@
(src/disamb/disambiguate/CheckTypeName.str (meta-c++-grammar/k/41_CheckTypeN 1.3 644))
(src/disamb/disambiguate/CheckNamespaceName.str (meta-c++-grammar/k/42_CheckNames 1.3 644))
(src/disamb/disambiguate/CheckEnumName.str (meta-c++-grammar/k/43_CheckEnumN 1.3 644))
(src/disamb/disambiguate/CheckClassName.str (meta-c++-grammar/k/44_CheckClass 1.4 644))
(src/disamb/disambiguate/CheckClassName.str (meta-c++-grammar/k/44_CheckClass 1.5 644))
(src/disamb/disambiguate/BaseTraverseCandidate.str (meta-c++-grammar/k/45_BaseTraver 1.3 644))
(src/disamb/disambiguate/BaseTraverse.str (meta-c++-grammar/k/46_BaseTraver 1.4 644))
(src/disamb/disambiguate/AmbiguityCandidate.str (meta-c++-grammar/k/47_AmbiguityC 1.3 644))
......@@ -888,6 +910,14 @@
(src/disamb/disambiguate/DeclaratorIdAmbiguity.str (meta-c++-grammar/p/9_Declarator 1.1 644))
(src/disamb/disambiguate/DeclaratorIdAmbiguity.meta (meta-c++-grammar/p/10_Declarator 1.1 644))
;; Files added by populate at Fri, 13 Feb 2004 18:12:36 +0100,
;; to version 0.150(w), by david_v:
(test/disambiguate/alias-01.cc (meta-c++-grammar/p/11_alias-01.c 1.1 644))
(test/disambiguate/alias-01.detcc (meta-c++-grammar/p/12_alias-01.d 1.1 644))
(src/disamb/disambiguate/GetKey.str (meta-c++-grammar/p/13_GetKey.str 1.1 644))
(src/disamb/disambiguate/GetKey.meta (meta-c++-grammar/p/14_GetKey.met 1.1 644))
)
(Merge-Parents)
(New-Merge-Parents)
......@@ -31,6 +31,7 @@ imports
Keys
Kinds
Lookup
GetKey
rules
......@@ -46,7 +47,8 @@ rules
CheckClassName : a@|ClassName[ ID ]| -> a
where < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; < lookup > c => class-kind
; (< lookup > c => class-kind
<+ < lookup > c => type-kind) // Bugfix for Std C++ grammar
; < print-key > d => e
; < concat-strings ; debug > ["Resolved ambiguity on name", " ", c, " ",
"in namespace", " ", e, " ",
......
......@@ -27,6 +27,7 @@ imports
AsFix2-Syntax
Identifier
TemplateArguments
GetKey
rules
......@@ -45,7 +46,8 @@ rules
where < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; < ?list-key (as); !as > d => d'
; < conc; ?x; !list-key (x) > (d', [string-key (c)]) => e
; < conc; ?x; !list-key (x) > (d', [string-key (c)])
; try(get-alias) => e
; < print-key > e => e'
; < concat-strings ; debug > ["Following nested name resolution to class", " ", e']
; < assert (!"$namespace") > ("$value", e)
......
/*
* Copyright (C) 2004 EPITA Research and Development Laboratory
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
module GetKey
imports
lib
imports
AsFix2-Syntax
asfix
Cxx
Identifier
Keys
signature
constructors
alias-table : Term -> Term
rules
TypeName-GetKey : |TypeName[ ~ClassName: |ClassName[ ID ]|~ ]| -> key
where < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; ( < scope(!"$namespace", lookup) > c => class-kind
; !list-key([string-key(c)])
<+ < scope(!"$namespace", lookup) > c => type-kind
; < get-alias > c)
; < ?(list-key(a), list-key(b)) > (d, <id>)
; !list-key(<conc>(a, b)) => key
TypeName-GetKey : |TypeName[ ~ClassName: |ClassName[ ~TemplateId: tid@|TemplateId[ID < TemplateArgumentList-opt > ]|~ ]|~ ]| -> key
where < identifier > ID => c
; < template-arguments > TemplateArgumentList-opt => g
; < rewrite (!"$namespace") > "$value" => d
; ( < scope(!"$namespace", lookup) > c => class-template-kind(_)
; !list-key([template-key(c,g)])
<+ < scope(!"$namespace", lookup) > c => type-kind
; < get-alias > c)
; < ?(list-key(a), list-key(b)) > (d, <id>)
; !list-key(<conc>(a, b)) => key
TypeName-GetKey : |TypeName[ ~TypedefName: |TypedefName[ ID ]|~ ]| -> key
where < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; < scope (!"$namespace", lookup) > c => type-kind
; < get-alias > c
; < ?(list-key(a), list-key(b)) > (d, <id>)
; !list-key(<conc>(a, b)) => key
SimpleTypeSpecifier-GetKey : |SimpleTypeSpecifier[ Dummy0-opt NestedNameSpecifier-opt TypeName ]| -> key
where < local-or-global > Dummy0-opt
; < try(
?|NestedNameSpecifier?[ ~NestedNameSpecifier: nested~ ]|;
!nested; nested-name-specifier; ?nested';
!|NestedNameSpecifier?[ ~NestedNameSpecifier: nested'~ ]|)
> NestedNameSpecifier-opt
; < TypeName-GetKey > TypeName => key
strategies
follow = rec x(?[e]; ![] <+ [id|x]) => ns
; <rewrite(!"$namespace")> "$value" => list-key(old)
; !list-key(<conc> (old, ns))
; <assert(!"$namespace")> ("$value", <id>)
; !e
get-alias = scope(!"$namespace",
list-key(follow; string-key(?d))
; !d
; lookup(!alias-table(<id>)) => list-key(al)
; <rewrite(!"$namespace")> "$value" => list-key(cur)
; !list-key(<conc> (cur, al))
; ?aliased
)
; !aliased
......@@ -35,18 +35,18 @@ rules
// environments.
//
Lookup : identifier -> result
Lookup(table) : identifier -> result
where < rewrite (!"$namespace") > "$value" => namespace
; < lookup-first > (namespace, identifier) => result
; < lookup-first(table) > (namespace, identifier) => result
//
// Lookup, and follow only the implicit dependency to outer
// namespaces.
//
Lookup' : identifier -> result
Lookup'(table) : identifier -> result
where < rewrite (!"$namespace") > "$value" => namespace
; < lookup-recurse > (namespace, identifier) => result
; < lookup-recurse(table) > (namespace, identifier) => result
//
// When the namespace list is empty, stop the lookup.
......@@ -60,45 +60,47 @@ rules
// namespace value to the current namespace.
//
Lookup-current : (namespace, identifier) -> result
where < rewrite (!namespace) > identifier => result
Lookup-current(table) : (namespace, identifier) -> result
where < rewrite (!namespace; table) > identifier => result
; < assert (!"$namespace") > ("$value", namespace)
//
// Recurse the lookup to the outer namespace.
//
Lookup-recurse : (namespace, identifier) -> result
Lookup-recurse(table) : (namespace, identifier) -> result
where < ?list-key (l); !l; reverse ; drop (!1); reverse; ?x; !list-key (x) > namespace => namespace'
; < lookup-recurse > (namespace', identifier) => result
; < lookup-recurse(table) > (namespace', identifier) => result
//
// Recurse the lookup to all the namespaces from which the current
// namespace inherits.
//
Lookup-inherit : (namespace, identifier) -> result
Lookup-inherit(table) : (namespace, identifier) -> result
where < rewrite (!namespace) > "$inherit" => inherit
; < lookup-pair > (identifier, inherit) => inherit'
; < getfirst (lookup-inherit) > inherit' => result
; < getfirst (lookup-inherit(table)) > inherit' => result
strategies
lookup = Lookup
lookup = Lookup(id)
lookup(table) = Lookup(table)
lookup' = Lookup'
lookup' = Lookup'(id)
loukup' = Lookup'(table)
lookup-first = (Lookup-stop;
Lookup-current) <+
lookup-first(table) = (Lookup-stop;
Lookup-current(table)) <+
(not (Lookup-stop);
(Lookup-current <+ Lookup-inherit <+ Lookup-recurse))
(Lookup-current(table) <+ Lookup-inherit(table) <+ Lookup-recurse(table)))
lookup-recurse = (Lookup-stop;
Lookup-current) <+
lookup-recurse(table) = (Lookup-stop;
Lookup-current(table)) <+
(not (Lookup-stop);
(Lookup-current <+ Lookup-recurse))
(Lookup-current(table) <+ Lookup-recurse(table)))
lookup-inherit = Lookup-current <+ Lookup-inherit
lookup-inherit(table) = Lookup-current(table) <+ Lookup-inherit(table)
lookup-pair = ( \ (x, []) -> [] \ ) <+
( \ (x, [y | ys]) -> [(y, x) | ys'] where < lookup-pair > (x, ys) => ys' \ )
......@@ -25,6 +25,7 @@ SRCS = \
EnumDefinition.str \
EnumDefinitionCandidate.str \
FunctionDefinitionAmbiguity.str \
GetKey.str \
IfDebug.str \
InitDeclaratorAmbiguity.str \
Keys.str \
......
......@@ -33,6 +33,10 @@ imports
strategies
type-ambiguity-cut = check-class-name <+
check-enum-name <+
check-type-name
// check-type-name must be placed before check-class-name because of a grammar
// bug fix.
type-ambiguity-cut = check-type-name <+
check-class-name <+
check-enum-name
/*
* Copyright (C) 2003 EPITA Research and Development Laboratory
* Copyright (C) 2003, 2004 EPITA Research and Development Laboratory
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -33,20 +33,31 @@ imports
rules
TypeDeclarator : a@|DeclaratorId[ ~IdExpression: |IdExpression[ ID ]|~ ]| -> a
where < identifier > ID => c
TypeDeclarator(s) : a@|DeclaratorId[ ~IdExpression: |IdExpression[ ID ]|~ ]| -> a
where s => []
; < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; < print-key > d => d'
; < concat-strings ; debug > ["Type", " ", c, " ", "being defined in namespace", " ", d']
; < assert (!d) > (c, type-kind)
TypeDeclarator(s) : a@|DeclaratorId[ ~IdExpression: |IdExpression[ ID ]|~ ]| -> a
where s; not([]) => alias
; < identifier > ID => c
; < rewrite (!"$namespace") > "$value" => d
; < print-key > d => d'
; < print-key > alias => alias'
; < concat-strings ; debug > ["Type", " ", c, " ", "being defined in namespace", " ", d', " aliasing to ", alias']
; < assert (!d) > (c, type-kind)
; < assert (!alias-table(d)) > (c, alias)
strategies
type-declarator-stop(s) = fail
type-declarator-single = (type-declarator-candidate;
TypeDeclarator) <+
not (type-declarator-candidate)
type-declarator-single(s) = where(type-declarator-candidate;
TypeDeclarator(s)) <+
not (type-declarator-candidate)
type-declarator = topdownS (type-declarator-single,
type-declarator-stop)
type-declarator(s) = topdownS (type-declarator-single(s),
type-declarator-stop)
......@@ -36,18 +36,26 @@ imports
rules
TypeDefinition-0 : a@|SimpleDeclaration[ DeclSpecifierSeq-opt la1 InitDeclaratorList-opt ; ]| -> |SimpleDeclaration[ DeclSpecifierSeq-opt la1 InitDeclaratorList-opt' ; ]|
where < topdownS(declarator-id-ambiguity
where (( <collect(?|SimpleTypeSpecifier[ Dummy0-opt NestedNameSpecifier-opt TypeName ]|)> DeclSpecifierSeq-opt => [n]
; <resolve> n
; SimpleTypeSpecifier-GetKey
<+ ![]) => alias )
; < topdownS(declarator-id-ambiguity
<+ not(declarator-id-ambiguity-candidate),
declarator-id-ambiguity-stop)
> InitDeclaratorList-opt
; type-declarator => InitDeclaratorList-opt'
; type-declarator(!alias) => InitDeclaratorList-opt'
TypeDefinition-1 : a@|MemberDeclaration[ DeclSpecifierSeq-opt la1 MemberDeclaratorList-opt ; ]| -> |MemberDeclaration[ DeclSpecifierSeq-opt la1 MemberDeclaratorList-opt' ; ]|
where < topdownS(declarator-id-ambiguity
where (( <collect(?|SimpleTypeSpecifier[ Dummy0-opt NestedNameSpecifier-opt TypeName ]|)> DeclSpecifierSeq-opt => [n]
; <resolve> n
; SimpleTypeSpecifier-GetKey
<+ ![]) => alias )
; < topdownS(declarator-id-ambiguity
<+ not(declarator-id-ambiguity-candidate),
declarator-id-ambiguity-stop)
> MemberDeclaratorList-opt
; type-declarator => MemberDeclaratorList-opt'
; type-declarator(!alias) => MemberDeclaratorList-opt'
strategies
......
......@@ -17,6 +17,7 @@ XFAIL_TESTS = \
template-08.test
TESTS = \
alias-01.test \
class-01.test \
class-02.test \
class-03.test \
......
// According to c++ standard syntax, this is invalid, but it is a bug in it.
// B will be forced to class-name against typedef-name.
struct A {
typedef int b;
};
typedef A B;
B::b i;
// According to c++ standard syntax, this is invalid, but it is a bug in it.
// B will be forced to class-name against typedef-name.
struct A {
typedef int /*<uid>*/b/*</uid>*/;
};
typedef /*<cl>*/A/*</cl>*/ /*<uid>*/B/*</uid>*/;
/*<ds>*//*<cl>*/B/*</cl>*/::/*<tn>*/b/*</tn>*//*</ds>*/ /*<uid>*/i/*</uid>*/;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment