<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 22, 2014, at 2:50 PM, Erik Olofsson <<a href="mailto:erik.olofsson@hansoft.com" class="">erik.olofsson@hansoft.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Hi Enrico,</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Thanks for looking into this.</div><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">On 2014-09-22, at 20:04, Enrico Granata <<a href="mailto:egranata@apple.com" class="">egranata@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Erik,<div class="">thanks for sending out this email. It is appreciated and valuable that you took the time to write this list of problems you encountered.<br class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Sep 20, 2014, at 3:42 PM, Erik Olofsson <<a href="mailto:erik.olofsson@hansoft.com" class="">erik.olofsson@hansoft.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Hi, </div><div class=""><br class=""></div><div class="">These are some of the issues I have run into when trying to add synthetic children and summary providers with the python API.</div><div class=""><br class=""></div><div class=""><b class="">Access to nested classes and typedefs</b></div><div class="">The first problem I ran into was accessing member typedefs of a SBType, for which I have found no API. The workaround for this was to create static variables with types I needed. This practice however would not be advisable in Release builds as it bloats the executable. This brings us to the second problem.</div></div></div></blockquote><div class=""><br class=""></div><div class="">You are probably correct about this. On the other hand, I don’t think I ever needed this ability. When exactly would this be useful?</div><div class="">I am of course not implying that we would not care to have this ability, just that I expect workarounds to exist.</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I have need this mostly for my intrusive containers. For example I have a tree template that takes a traits type. Inside this traits type I need to get to the typedef for the node type. Also getting back to the container type from an iterator.</div></div></div></blockquote><div><br class=""></div><div>Fair enough. I usually get away with inspecting template arguments to figure these things out, but I can see that as being useful.</div><div>Worthy of a bugzilla.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class=""><b class="">Access to class member static variables</b></div><div class="">There is no way to access static member variables directly from a SBValue or SBType. The current method I use works for some cases but not all:</div><div class=""><br class=""></div><div class="">SBValue.CreateValueFromExpression(SBValue.get_expr_path() + ("." or "->") + StaticVarName) </div><div class=""><span class="Apple-tab-span" style="white-space: pre;"> </span>This works for normal SBValues, but not synthetic SBValues</div><div class=""><br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">Indeed. Known problem, but most likely very hard to solve, and not even desirable in all cases. See below, but this has been discussed already somewhere in greater detail.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">SBValue.CreateValueFromExpression(SBType.GetName() + "::" + StaticVarName) </div><div class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>This fails for template types as it fails to parse the template</div><div class=""><br class=""></div><div class="">SBValue.GetFrame().GetVariables(False, False, True, False); </div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>This fails for statics not in the current compilation unit</div><div class=""><br class=""></div><div class="">SBValue.GetTarget().FindGlobalVariables(StaticVarName, 1024); </div><div class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>This fails because not nearly all statics are returned. Also if you specify the class, it is just ignored and you need to compare SBValue.GetName() against the SBType.GetName() + StaticVarName. But that also fails sometimes because the name in SBType and SBValue is not always formatted the same way for template (non-type) params.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Worth filing a bugzilla for. Or maybe Greg has some magical insight on how to find all the things.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class=""><b class="">Expressions on synthetic SBValues</b></div><div class="">You cannot access synthetic SBValues in an expression in any way as far as I can tell. I have found no way to get an arbitrary type and pointer into an expression for evaluation. For simple types it works to just use the address and cast it to the correct type:  "(Type *)0xXXXXXXXX". But this does not work for template types as parsing them invariably fails (error: no type named 'X' in namespace 'X::X’).</div></div></div></blockquote><div class=""><br class=""></div><div class="">You can’t. That is entirely by design. Imagine having an std::map<string,int></div><div class="">In code, you write myMap[“key”], but synthetic children are exposed as myMap[0], as a pair<keyType,valueType></div><div class="">If synthetic children were allowed, now you could write myMap[0] = 12, or myMap[0] = {“1”,2} or other horrible things that you should not be allowed to write, with dubious semantics at best.</div><div class="">There are a few more caveats, but long story short, it’s a tricky business, and we just don’t have enough of a compelling use case/right answers to want to delve into it</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, I agree you shouldn't be able to access child synthetics through expressions. The problem is that there is no way to get an synthetic SBValue into an expression in any way. The only thing needed is to access the "this" of a SBValue, not synthetic children of an arbitrary SBValue. Consider the following scenario:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>struct Type</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>{</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">               </span>const char *DebugFormat();</div><div class=""><span class="Apple-tab-span" style="white-space: pre;"> </span>};</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>map<Type> Map;</div><div class=""><br class=""></div><div class="">Getting the synthetic children of this Map returns a SBValue created with:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;"> </span>SBValue.CreateValueFromAddress('[0]', NodeAddress, NodeType)</div><div class=""><br class=""></div><div class="">This synthetic value is in turn sent to a summary provider which wants to call DebugFormat:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>ValueObject.CreateValueFromExpression(ValueObject.get_expr_path() + ".DebugFormat()")</div><div class=""><br class=""></div><div class="">This works for a plain variable, but not when evaluating the synthetic child of the Map, where get_expr_path() returns [0], which gives [0].DebugFormat().</div><div class=""><br class=""></div><div class="">Of course this example can be worked around by casting a pointer to the type, but this also loses context. What if there are several types with the same name in different modules for example. And for my case it doesn't work for templates.</div><div class=""><br class=""></div><div class="">A way to support this would for example be to allow the SBValue that you call CreateValueFromExpression on to be accessed through a special variable a bit like the persistent variables. So in this case I would want to call:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>ValueObject.CreateValueFromExpression("$this.DebugFormat()") # $this is ValueObject</div><div class=""><br class=""></div><div class="">Keep in mind that my use case for this is primarily for expanding variables in the Xcode debugger.</div></div></div></blockquote><div><br class=""></div><div>We did chat about this a bit, and we came up with a scheme of a solution. As you noticed, the problem is that GetExpressionPath() "makes no sense” (in an expression-<i class="">y</i> sense) for synthetic children</div><div>There are mainly two kinds of synthetic children:</div><div>- ones that actually exist in inferior memory</div><div>- ones that are made up by LLDB as a result of computation</div><div><br class=""></div><div>The first category of children should just return a feasible expression path, e.g. (*((MyType*)address))</div><div>Now you would be able to type (*((MyType*)address).DebugFormat() and things would work</div><div><br class=""></div><div>If you actually computed something (e.g. the length of a string) but it does not exist anywhere, then you can either get a raw value back, e.g. (int)5, or actually no expression path at all - and that would indicate “hey tough luck, can’t use this”</div><div><br class=""></div><div>There are a few advantages to this (apart from simplicity), mostly that since you’re modifying the actual object in inferior memory, your view of the world will be meaningful, i.e. there will be no bias between the synthetic children and the reality you just tweaked</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class=""><div class=""><b class="">Non Type Template Params</b></div><div class="">For some types I need to get non type template param values. I have found no API for this, although this can be worked around by adding static variables with the values in them.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">This sounds like a bug. Maybe a DWARF problem. Do you have a reproduction case handy?</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I think it's just a missing API. Currently you have SBType.GetTemplateArgumentType, while I would need something like: SBType.GetTemplateArgumentValue to get the value of a non-type template param. </div></div></div></blockquote><div><br class=""></div><div>Bugzilla here!</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class=""><b class="">Access to posix thread locals</b></div><div class="">I have found no way to access pthread thread locals, or reading through the GS segment of a thread from the python API, so I have to resort to calling into the target. But I guess that is no problem as long as I don't need to debug a core dump (if or when this is supported).</div><div class=""><br class=""></div><div class=""><b class="">Suggestions</b></div><div class="">To get everything working:</div><div class="">* Add API for saving a SBValue as a persistent variable. This would allow a workaround for doing expressions on synthetic SBValues</div></div></div></blockquote><div class=""><br class=""></div><div class="">This might be interesting. Worth filing a bugzilla ER for.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">or</div><div class="">* You should be able to access the SBValue in the expression when calling: SBValue.CreateValueFromExpression. For example: $var, or the context of the evaluation should be as if inside a class function of the type of the SBValue, which would allow you to access the member vars directly.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I don’t think we’d want to go for language extensions. Doesn’t this->whatever work, if you are currently stopped in a class context?</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">See above, it's the case when expanding a container in Xcode, when you need to do expressions on the resulting synthetic value. Also you already have the language extension in there for persistent variables. You would only need to reserve one of them for this purpose ($this).</div><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">To not have to add helpers in target executable:</div><div class="">* Add API to access nested types and typedefs in a SBType</div><div class="">* Add API to get static class members: SBValue.GetChildStaticMemberWithName, and SBType.GetChildStaticMemberWithName</div><div class="">* Add API to read the from the GS segment of a thread, or support for reading pthread thread locals.</div></div></div></blockquote><div class=""><br class=""></div><div class="">These seem all worth of bug/ER reports, although Greg might know more about thread local access</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Any ideas for workarounds for these issue would be appreciated. Currently I would be happy to just get it to work reliably, for which all I need is to be able to get an arbitrary SBValue into an expression. </div></div></div></blockquote><div class=""><br class=""></div><div class="">Why do you need to use an expression? For 99% of formatters, that is usually not desirable nor necessary.</div><div class="">Not desirable for performance and stability reasons. Not necessary because most often all the expression does is memory access and basic manipulations that are doable via Python anyway</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I agree, I use expressions only when there is no other way. Currently I need to use expressions to get to static member variables, which is the foundation for working around all the other limitations. </div></div></div></blockquote><div><br class=""></div><div>That should work</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">Also sometimes it's just too much work to create a formatter in Python. For example I have a case with a templated float type that lets you choose the number of bits for the mantissa and exponent. Creating code in Python to format these into a string would be a lot of work.</div></div></div></blockquote><div><br class=""></div><div>It is probably some chunk of work, yes.</div><div>On the other hand, the whole “run expressions” business will likely end up slowing you down, and potentially causing headaches down the road when you try to debug something in a really funky state.</div><div>It is quite discouraged to run expressions to format objects. Sure, sometimes <i class="">you gotta do what you gotta do</i>, but caveat emptor. </div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">If I were to try to patch this myself, what do you think would be the easiest:</div><div class="">* Fix the template parsing in expressions.</div></div></div></blockquote><div class=""><br class=""></div><div class="">If you have cases of expressions that we should parse and aren’t, please file bugs</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I will look into reducing the cases I have found. I have a suspicion that it's not the parsing that is at fault, but that the template types are not being included for consideration.</div><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">* Save SBValue as persistent variable.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Not a bad idea, but probably not necessary either</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">* Access SBValue directly in expression through $var</div></div></div></blockquote><div class=""><br class=""></div><div class="">There are good reasons to not do that</div></div></div></div></div></blockquote><div class=""><br class=""></div>Taken the explanation above, are you still of the same opinion?</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">* Access the SBValue directly in expression by being evaluated in the context of type of the SBValue</div></div></div></blockquote><div class=""><br class=""></div><div class="">Depending on where you’re stopped this should either work already or hardly be meaningful (if I understand what you mean)</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">This only applies to synthetic SBValues, which have no context in the current frame. This would inject a context when CreateValueFromExpression is called through a SBValue. SBTarget.EvaluateExpression would work exactly like before. But I can imagine this would be messy to implement.</div><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">Regards,</div><div class="">Erik</div><div class=""><br class=""></div></div>_______________________________________________<br class="">lldb-dev mailing list<br class=""><a href="mailto:lldb-dev@cs.uiuc.edu" class="">lldb-dev@cs.uiuc.edu</a><br class=""><a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev" class="">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev</a><br class=""></div></blockquote></div><br class=""><div class=""><div class="" style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="" style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="" style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="" style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="" style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Thanks,</div><div class=""><i class="">- Enrico</i><br class="">📩 egranata@<font color="#ff2600" class=""></font>.com ☎️ 27683</div><div class=""><br class=""></div></div></div></div></div></div><br class="Apple-interchange-newline"></div></div></div></div></blockquote></div><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Regards,</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Erik</div></div></blockquote></div><br class=""><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Thanks,</div><div class=""><i class="">- Enrico</i><br class="">📩 egranata@<font color="#ff2600" class=""></font>.com ☎️ 27683</div><div class=""><br class=""></div></div></div></div></div></div><br class="Apple-interchange-newline"><br class="Apple-interchange-newline">
</div>
<br class=""></body></html>