Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:17204 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 3420 invoked by uid 1010); 9 Jul 2005 06:39:34 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 3405 invoked from network); 9 Jul 2005 06:39:34 -0000 Received: from unknown (HELO pb1.pair.com) (127.0.0.1) by localhost with SMTP; 9 Jul 2005 06:39:34 -0000 X-Host-Fingerprint: 68.215.123.37 adsl-215-123-37.mia.bellsouth.net Received: from ([68.215.123.37:4132] helo=localhost.localdomain) by pb1.pair.com (ecelerity 1.2 r(5656M)) with SMTP id 3E/B3-59389-6217FC24 for ; Sat, 09 Jul 2005 02:39:34 -0400 Message-ID: <3E.B3.59389.6217FC24@pb1.pair.com> To: internals@lists.php.net Date: Sat, 09 Jul 2005 02:39:24 -0400 References: <84.75.05285.5EA7CC24@pb1.pair.com> Lines: 526 User-Agent: KNode/0.8.1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart1331692.RPlukYx4rK" Content-Transfer-Encoding: 7Bit X-Posted-By: 68.215.123.37 Subject: Re: YANP (Yet Another Namespace Proposal) From: jrhernandez05@gmail.com (Jessie Hernandez) --nextPart1331692.RPlukYx4rK Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8Bit For previewing purposes, I have attached a patch of what I have so far so that others can look at it and try it out. I have also attached two PHP files for testing (_testns.php is the script that should be run after the patch is applied. This script includes a class from class3.php to demonstrate two things: namespaces may be spread out in files, and classes do not have to be immediately available for imports to work). I based my patch on PHP 5.1.0b2 (not CVS, yet). I have not used the diff utility before, but here is the command I ran to produce the patch (let me know if there's a better way): diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend php-5.1.0b2/Zend/ > ns.patch Anyways, all the features I've mentioned have been enabled in the patch except the following: 1) Automatic including of class files. 2) Wildcard imports (or full namespace imports). I have been checking the code to see what it would take to apply the current include/require logic against a different INI variable (class_path), but I digged deeper and deeper into the code and got lost in the streams functions. So far, it seems I have to create my own opcode (like ZEND_INCLUDE_OR_EVAL), and when that's encountered, then call whatever stream function is needed to perform the include against class_path. It seems like it will take me some time to figure this out, so that's why I haven't included it yet (maybe someone can help me?). Please try it out and let me know what you think. I believe this solution compiles the code to be the equivalent of prefixing all classes, so I think most of the issues presented in the archives are solved with this solution. Let me know if you need anything else from me to get it working on your installation. Also, I'm not sure if there are any attachment restrictions in this group (email me privately if you can't open the files). -- Jessie --nextPart1331692.RPlukYx4rK Content-Type: application/x-php; name="_class3.php" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="_class3.php" PD9waHAKbmFtZXNwYWNlIG15X25zCnsKCWNsYXNzIGNsYXNzMwoJewoJCXB1YmxpYyAkbWVtMyA9 IDc7Cgl9Cn0KPz4K --nextPart1331692.RPlukYx4rK Content-Type: text/x-diff; name="ns.patch" Content-Transfer-Encoding: 8Bit Content-Disposition: attachment; filename="ns.patch" diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend.c php-5.1.0b2/Zend/zend.c --- php-5.1.0b2-bak/Zend/zend.c 2005-06-15 15:05:55.000000000 -0400 +++ php-5.1.0b2/Zend/zend.c 2005-07-09 00:44:41.000000000 -0400 @@ -34,10 +34,12 @@ # define GLOBAL_CLASS_TABLE global_class_table # define GLOBAL_CONSTANTS_TABLE global_constants_table # define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table +# define GLOBAL_IMPORT_CLASS_TABLE global_import_class_table #else # define GLOBAL_FUNCTION_TABLE CG(function_table) # define GLOBAL_CLASS_TABLE CG(class_table) # define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) +# define GLOBAL_IMPORT_CLASS_TABLE CG(import_class_table) #endif #if defined(ZEND_WIN32) && ZEND_DEBUG @@ -88,6 +90,7 @@ HashTable *global_class_table; HashTable *global_constants_table; HashTable *global_auto_globals_table; +HashTable *global_import_class_table; #endif ZEND_API zend_utility_values zend_uv; @@ -430,6 +433,7 @@ { zend_function tmp_func; zend_class_entry *tmp_class; + zval tmp_zval; compiler_globals->compiled_filename = NULL; @@ -443,6 +447,16 @@ zend_set_default_compile_time_values(TSRMLS_C); + /* initialize namespace variables */ + compiler_globals->namespace_prefix = NULL; + compiler_globals->namespace_prefix_lc = NULL; + compiler_globals->namespace_prefix_len = 0; + + /* initialize the import table */ + compiler_globals->import_class_table = (HashTable *) malloc(sizeof(HashTable)); + zend_hash_init_ex(compiler_globals->import_class_table, 10, NULL, ZVAL_DESTRUCTOR, 1, 0); + zend_hash_copy(compiler_globals->import_class_table, global_import_class_table, NULL, &tmp_zval, sizeof(zval)); + CG(interactive) = 0; compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable)); @@ -465,6 +479,10 @@ zend_hash_destroy(compiler_globals->auto_globals); free(compiler_globals->auto_globals); } + if (compiler_globals->import_class_table != GLOBAL_IMPORT_CLASS_TABLE) { + zend_hash_destroy(compiler_globals->import_class_table); + free(compiler_globals->import_class_table); + } } @@ -588,11 +606,13 @@ GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable)); GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); + GLOBAL_IMPORT_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); #ifdef ZTS GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable)); #endif zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0); + zend_hash_init_ex(GLOBAL_IMPORT_CLASS_TABLE, 10, NULL, ZVAL_DESTRUCTOR, 1, 0); zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0); zend_init_rsrc_list_dtors(); @@ -618,10 +638,12 @@ compiler_globals->in_compilation = 0; compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable)); compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); + compiler_globals->import_class_table = (HashTable *) malloc(sizeof(HashTable)); *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE; *compiler_globals->class_table = *GLOBAL_CLASS_TABLE; compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE; + *compiler_globals->import_class_table = *GLOBAL_IMPORT_CLASS_TABLE; zend_hash_destroy(executor_globals->zend_constants); *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE; @@ -676,9 +698,11 @@ *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; + *GLOBAL_IMPORT_CLASS_TABLE = *compiler_globals->import_class_table; zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC); free(compiler_globals->function_table); free(compiler_globals->class_table); + free(compiler_globals->import_class_table); compiler_globals_ctor(compiler_globals, tsrm_ls); free(EG(zend_constants)); executor_globals_ctor(executor_globals, tsrm_ls); @@ -699,6 +723,7 @@ zend_hash_destroy(GLOBAL_FUNCTION_TABLE); zend_hash_destroy(GLOBAL_CLASS_TABLE); + zend_hash_destroy(GLOBAL_IMPORT_CLASS_TABLE); zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); free(GLOBAL_AUTO_GLOBALS_TABLE); @@ -709,6 +734,7 @@ zend_shutdown_constants(TSRMLS_C); free(GLOBAL_FUNCTION_TABLE); free(GLOBAL_CLASS_TABLE); + free(GLOBAL_IMPORT_CLASS_TABLE); #ifdef ZTS zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC); zend_hash_destroy(GLOBAL_CONSTANTS_TABLE); @@ -716,6 +742,7 @@ GLOBAL_FUNCTION_TABLE = NULL; GLOBAL_CLASS_TABLE = NULL; GLOBAL_AUTO_GLOBALS_TABLE = NULL; + GLOBAL_IMPORT_CLASS_TABLE = NULL; #endif zend_destroy_rsrc_list_dtors(); } diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend_compile.c php-5.1.0b2/Zend/zend_compile.c --- php-5.1.0b2-bak/Zend/zend_compile.c 2005-06-22 04:32:57.000000000 -0400 +++ php-5.1.0b2/Zend/zend_compile.c 2005-07-09 00:44:41.000000000 -0400 @@ -1385,10 +1384,12 @@ zval_dtor(&class_name->u.constant); break; default: + zend_resolve_class_name_node(class_name TSRMLS_CC); opline->op2 = *class_name; break; } } else { + zend_resolve_class_name_node(class_name TSRMLS_CC); opline->op2 = *class_name; } opline->result.u.var = get_temporary_variable(CG(active_op_array)); @@ -2615,6 +2616,11 @@ zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val); } + /* fully prefix the class name */ + efree(lcname); + zend_prefix_class_name_node(class_name TSRMLS_CC); + lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); + new_class_entry->type = ZEND_USER_CLASS; new_class_entry->name = class_name->u.constant.value.str.val; new_class_entry->name_length = class_name->u.constant.value.str.len; @@ -2659,8 +2665,151 @@ CG(doc_comment) = NULL; CG(doc_comment_len) = 0; } + +} + +/***************************** + * BEGIN NAMESPACE FUNCTIONS * + *****************************/ + +void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC) +{ + /* allocate space for the namespace prefix */ + CG(namespace_prefix) = emalloc(ns_name->u.constant.value.str.len + 2); + *CG(namespace_prefix) = '\0'; + + /* get the namespace prefix */ + strcat(CG(namespace_prefix), ns_name->u.constant.value.str.val); + strcat(CG(namespace_prefix), ":"); + + /* get the lowercased namespace prefix */ + CG(namespace_prefix_lc) = zend_str_tolower_dup(CG(namespace_prefix), ns_name->u.constant.value.str.len + 1); + + /* save the prefix length */ + CG(namespace_prefix_len) = ns_name->u.constant.value.str.len + 1; +} + +void zend_do_end_namespace(znode *ns_token TSRMLS_DC) +{ + /* free the string memory */ + efree(CG(namespace_prefix)); + efree(CG(namespace_prefix_lc)); + CG(namespace_prefix_len) = 0; + + /* set the prefixes to null */ + CG(namespace_prefix) = NULL; + CG(namespace_prefix_lc) = NULL; +} + +void zend_do_import(znode *class_name, znode *alias_name TSRMLS_DC) +{ + char *alias_name_lc = NULL; + zend_uint alias_name_len = 0; + zval alias_val; + /* 'colon_pos' is the position of the last colon in the full class name */ + char *colon_pos = strrchr(class_name->u.constant.value.str.val, ':'); + /* 'last_pos' is the position of the null terminator in the full class name */ + char *last_pos = class_name->u.constant.value.str.val + class_name->u.constant.value.str.len; + + if (colon_pos == NULL) { + zend_error(E_COMPILE_ERROR, "Cannot import non-namespace class: %s!", class_name->u.constant.value.str.val); + return; + } + + if (alias_name == NULL) { + /* advance to the first character of the class name */ + ++colon_pos; + + /* get the lowercased class name as the alias */ + alias_name_len = last_pos - colon_pos; + alias_name_lc = zend_str_tolower_dup(colon_pos, alias_name_len); + } else /* alias_name != NULL */ { + alias_name_lc = zend_str_tolower_dup(alias_name->u.constant.value.str.val, alias_name->u.constant.value.str.len); + alias_name_len = alias_name->u.constant.value.str.len; + } + + /* make sure this import alias is not the same as a class name */ + if (zend_hash_exists(CG(class_table), alias_name_lc, alias_name_len + 1)) { + zend_error(E_COMPILE_ERROR, "Could not import %s as %s: a class exists with the name %s", class_name->u.constant.value.str.val, alias_name_lc, alias_name_lc); + return; + } + + /* make sure this import alias has not been used before */ + if (zend_hash_exists(CG(import_class_table), alias_name_lc, alias_name_len + 1)) { + zend_error(E_COMPILE_ERROR, "An import was already done with the %s alias", alias_name_lc); + return; + } + + /* initialize the full class name zval */ + INIT_ZVAL(alias_val); + alias_val.value.str.val = estrdup(class_name->u.constant.value.str.val); + alias_val.value.str.len = class_name->u.constant.value.str.len; + + /* add the alias */ + if (zend_hash_add(CG(import_class_table), alias_name_lc, alias_name_len + 1, &alias_val, sizeof(alias_val), NULL) == FAILURE) { + zend_error(E_COMPILE_ERROR, "Could not import %s as %s!", class_name->u.constant.value.str.val, alias_name_lc); + return; + } + + efree(alias_name_lc); +} + +void zend_do_namespace_import(znode *ns_name TSRMLS_DC) +{ +} + +void zend_do_unimport_all(TSRMLS_D) +{ + zend_hash_clean(CG(import_class_table)); +} + +void zend_prefix_class_name_node(znode *class_name TSRMLS_DC) +{ + zend_uint new_length = 0; + char *org_class_name = NULL; + + if (CG(namespace_prefix) != NULL) { + new_length = CG(namespace_prefix_len) + class_name->u.constant.value.str.len; + org_class_name = estrdup(class_name->u.constant.value.str.val); + + STR_REALLOC(class_name->u.constant.value.str.val, new_length + 1); + + /* prepare for strcat */ + *class_name->u.constant.value.str.val = '\0'; + + /* get the full class name */ + strcat(class_name->u.constant.value.str.val, CG(namespace_prefix)); + strcat(class_name->u.constant.value.str.val, org_class_name); + + /* get the new string length */ + class_name->u.constant.value.str.len = new_length; + + efree(org_class_name); + } +} + +void zend_resolve_class_name_node(znode *class_name TSRMLS_DC) +{ + zval* mapped_class_name = NULL; + char *org_class_name = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); + zend_uint org_class_name_len = class_name->u.constant.value.str.len; + + /* check to see if this class name is actually an import alias */ + if (zend_hash_find(CG(import_class_table), org_class_name, org_class_name_len + 1, (void **)&mapped_class_name) == SUCCESS) { + /* free the class name string */ + STR_FREE(class_name->u.constant.value.str.val); + + /* set the class node to contain the full class name */ + class_name->u.constant.value.str.val = estrdup(mapped_class_name->value.str.val); + class_name->u.constant.value.str.len = mapped_class_name->value.str.len; + } + + efree(org_class_name); } +/*************************** + * END NAMESPACE FUNCTIONS * + ***************************/ static void do_verify_abstract_class(TSRMLS_D) { diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend_compile.h php-5.1.0b2/Zend/zend_compile.h --- php-5.1.0b2-bak/Zend/zend_compile.h 2005-06-22 04:32:57.000000000 -0400 +++ php-5.1.0b2/Zend/zend_compile.h 2005-07-09 00:44:41.000000000 -0400 @@ -438,6 +438,14 @@ void zend_do_declare_implicit_property(TSRMLS_D); void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC); +void zend_do_begin_namespace(znode *ns_token, znode *ns_name TSRMLS_DC); +void zend_do_end_namespace(znode *ns_token TSRMLS_DC); +void zend_do_import(znode *class_name, znode *alias_name TSRMLS_DC); +void zend_do_namespace_import(znode *ns_name TSRMLS_DC); +void zend_do_unimport_all(TSRMLS_D); +void zend_prefix_class_name_node(znode *class_name TSRMLS_DC); +void zend_resolve_class_name_node(znode *class_name TSRMLS_DC); + void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC); diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend_globals.h php-5.1.0b2/Zend/zend_globals.h --- php-5.1.0b2-bak/Zend/zend_globals.h 2004-11-03 18:13:32.000000000 -0500 +++ php-5.1.0b2/Zend/zend_globals.h 2005-07-09 00:44:41.000000000 -0400 @@ -143,6 +143,13 @@ zend_encoding_converter encoding_converter; zend_encoding_oddlen encoding_oddlen; #endif /* ZEND_MULTIBYTE */ + + /* namespace variables */ + char *namespace_prefix; + char *namespace_prefix_lc; + zend_uint namespace_prefix_len; + + HashTable *import_class_table; }; diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend_language_parser.y php-5.1.0b2/Zend/zend_language_parser.y --- php-5.1.0b2-bak/Zend/zend_language_parser.y 2005-06-08 02:49:00.000000000 -0400 +++ php-5.1.0b2/Zend/zend_language_parser.y 2005-07-09 02:20:28.000000000 -0400 @@ -145,11 +145,13 @@ %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM - +%token T_IMPORT +%token T_NAMESPACE_NAME +%token T_NAMESPACE %% /* Rules */ start: - top_statement_list + top_statement_list { zend_do_unimport_all(TSRMLS_C); } ; top_statement_list: @@ -162,6 +164,7 @@ statement | function_declaration_statement { zend_do_early_binding(TSRMLS_C); } | class_declaration_statement { zend_do_early_binding(TSRMLS_C); } + | namespace_declaration_statement | T_HALT_COMPILER '(' ')' ';' { REGISTER_MAIN_LONG_CONSTANT("__COMPILER_HALT_OFFSET__", zend_get_scanned_file_offset(TSRMLS_C), CONST_CS); YYACCEPT; } ; @@ -231,6 +234,10 @@ '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); } | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } + | T_IMPORT T_NAMESPACE_NAME ';' { zend_do_import(&$2, NULL TSRMLS_CC); } + | T_IMPORT T_NAMESPACE_NAME T_AS T_STRING ';' { zend_do_import(&$2, &$4 TSRMLS_CC); } + | T_IMPORT T_NAMESPACE T_NAMESPACE_NAME ';' { zend_do_namespace_import(&$3 TSRMLS_CC); } + | T_IMPORT T_NAMESPACE T_STRING ';' { zend_do_namespace_import(&$3 TSRMLS_CC); } ; @@ -307,6 +314,19 @@ | T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_FINAL_CLASS; } ; +namespace_declaration_statement: + T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$1, &$2 TSRMLS_CC); } namespace_statement_list '}' { zend_do_end_namespace(&$1 TSRMLS_CC); } +; + +namespace_statement_list: + namespace_statement_list namespace_statement + | /* empty */ +; + +namespace_statement: + class_declaration_statement { zend_do_early_binding(TSRMLS_C); } +; + extends_from: /* empty */ { $$.op_type = IS_UNUSED; } | T_EXTENDS fully_qualified_class_name { $$ = $2; } @@ -639,10 +659,12 @@ fully_qualified_class_name: T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | T_NAMESPACE_NAME { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ; class_name_reference: T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | T_NAMESPACE_NAME { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } | dynamic_class_name_reference { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ; @@ -654,6 +676,10 @@ | base_variable { $$ = $1; } ; +namespace_name: + T_NAMESPACE_NAME { $$ = $1; } + | T_STRING { $$ = $1; } +; dynamic_class_name_variable_properties: dynamic_class_name_variable_properties dynamic_class_name_variable_property Only in php-5.1.0b2/Zend/: zend_language_parser.y~ diff -Bbruw -X diff_exclude.txt php-5.1.0b2-bak/Zend/zend_language_scanner.l php-5.1.0b2/Zend/zend_language_scanner.l --- php-5.1.0b2-bak/Zend/zend_language_scanner.l 2005-06-16 09:31:21.000000000 -0400 +++ php-5.1.0b2/Zend/zend_language_scanner.l 2005-07-09 00:44:41.000000000 -0400 @@ -790,6 +790,7 @@ ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+ ANY_CHAR (.|[\n]) NEWLINE ("\r"|"\n"|"\r\n") +NAMESPACE_NAME ({LABEL}":")*{LABEL} %option noyylineno %option noyywrap @@ -923,6 +924,14 @@ return T_CLASS; } +"namespace" { + return T_NAMESPACE; +} + +"import" { + return T_IMPORT; +} + "interface" { return T_INTERFACE; } @@ -1433,6 +1442,13 @@ return T_STRING; } +{NAMESPACE_NAME} { + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return T_NAMESPACE_NAME; +} + {LABEL} { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; --nextPart1331692.RPlukYx4rK Content-Type: application/x-php; name="_testns.php" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="_testns.php" PD9waHAKcmVxdWlyZV9vbmNlKCBkaXJuYW1lKCBfX0ZJTEVfXyApIC4gJy9fY2xhc3MzLnBocCcg KTsKCmNsYXNzIHJlZ3VsYXJfY2xhc3MKewoJcHVibGljICRtZW0gPSAxOwp9CgpuYW1lc3BhY2Ug bXlfbnMKewoJY2xhc3MgY2xhc3MxCgl7CgkJcHVibGljICRtZW0xID0gMzsKCX0KCgljbGFzcyBj bGFzczIKCXsKCQlwdWJsaWMgJG1lbTIgPSA1OwoJCXB1YmxpYyBzdGF0aWMgJG15X3N0YXRpYyA9 ICd0aGlzIGlzIHN0YXRpYyc7Cgl9Cn0KCmltcG9ydCBteV9uczpjbGFzczE7CmltcG9ydCBteV9u czpjbGFzczIgYXMgbXlfbnNfY2xhc3MyOwppbXBvcnQgbXlfbnM6Y2xhc3MzOwoKJHJjID0gbmV3 IHJlZ3VsYXJfY2xhc3MoKTsKdmFyX2R1bXAoICRyYyApOwoKJGMwID0gbmV3IG15X25zOmNsYXNz MSgpOwp2YXJfZHVtcCggJGMwICk7CgokYzEgPSBuZXcgY2xhc3MxKCk7CnZhcl9kdW1wKCAkYzEg KTsKCiRjMiA9IG5ldyBteV9uc19jbGFzczIoKTsKdmFyX2R1bXAoICRjMiApOwoKJGMzID0gbmV3 IGNsYXNzMygpOwp2YXJfZHVtcCggJGMzICk7CgplY2hvIG15X25zOmNsYXNzMjo6JG15X3N0YXRp YywgIlxuIjsKPz4KCg== --nextPart1331692.RPlukYx4rK--