<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<id>tag:old.nabble.com,2006:forum-14098</id>
	<title>Nabble - Erlang Patches</title>
	<updated>2009-11-10T09:27:57Z</updated>
	<link rel="self" type="application/atom+xml" href="http://old.nabble.com/Erlang-Patches-f14098.xml" />
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Erlang-Patches-f14098.html" />
	<subtitle type="html">Send patches for Erlang/OTP and give feedback about the submitted patches.</subtitle>
	
<entry>
	<id>tag:old.nabble.com,2006:post-26287687</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in get_diagnos function</title>
	<published>2009-11-10T09:27:57Z</published>
	<updated>2009-11-10T09:27:57Z</updated>
	<author>
		<name>Andrew Thompson-15</name>
	</author>
	<content type="html">Any feedback from the erlang team on this? I'm willing to work on the
&lt;br&gt;patch if its not satisfactory.
&lt;br&gt;&lt;br&gt;Andrew
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p26287687.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26166514</id>
	<title>ASN1 BER bit string encoding</title>
	<published>2009-11-02T08:21:28Z</published>
	<updated>2009-11-02T08:21:28Z</updated>
	<author>
		<name>Anders Nygren</name>
	</author>
	<content type="html">Hi
&lt;br&gt;When encoding a bit string, that has a size constraint that is a
&lt;br&gt;range, and the value to encode
&lt;br&gt;is given using 'named bits', the encoded value always contains the
&lt;br&gt;maximum number of bits.
&lt;br&gt;This is a little inefficient since it forces the transmission of more
&lt;br&gt;bits that necessary.
&lt;br&gt;&lt;br&gt;This is not a real problem, except that we have to communicate with a
&lt;br&gt;node that rejects the
&lt;br&gt;message if the encoded bit string contains more than the minimum number of bits.
&lt;br&gt;&lt;br&gt;Also it might be a good idea to change lists:sort to lists:usort in
&lt;br&gt;asn1rt_ber_bin:get_all_bitposes/3 in order to not getting an error if
&lt;br&gt;the same named bit
&lt;br&gt;is specified more than once/
&lt;br&gt;&lt;br&gt;/Anders
&lt;br&gt;&lt;br /&gt;&lt;tt&gt;[asn1rt_berbin.patch]&lt;/tt&gt;&lt;br /&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;tt&gt;diff otp_src_R13B02-1/lib/asn1/src//asn1rt_ber_bin.erl otp_src_R13B02-1_my/lib/asn1/src//asn1rt_ber_bin.erl
&lt;br&gt;1268c1268,1269
&lt;br&gt;&amp;lt; 		BitList = make_and_set_list(Max, ToSetPos, 0),
&lt;br&gt;---
&lt;br&gt;&amp;gt; 		BitsToEnc=lists:min([Max,lists:max([_Min,lists:last(ToSetPos)+1])]),
&lt;br&gt;&amp;gt; 		BitList = make_and_set_list(BitsToEnc, ToSetPos, 0),
&lt;br&gt;Only in otp_src_R13B02-1_my/lib/asn1/src/: asn1rt_ber_bin.erl~
&lt;br&gt;&lt;/tt&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ASN1-BER-bit-string-encoding-tp26166514p26166514.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26022739</id>
	<title>Re: small patch for tv</title>
	<published>2009-10-23T01:39:32Z</published>
	<updated>2009-10-23T01:39:32Z</updated>
	<author>
		<name>Dmitriy Budashny</name>
	</author>
	<content type="html">&lt;div&gt;My last letter was written w/o testing for other problems, I&amp;#39;ve found there were other calls to lists:nthtail/2.&lt;/div&gt;&lt;div&gt;I&amp;#39;ve attached a new patch file in this letter&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;div class=&quot;gmail_quote&quot;&gt;2009/10/22 Dmitriy Budashny &lt;span dir=&quot;ltr&quot;&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26022739&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;dmitriy.budashny@...&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;blockquote class=&quot;gmail_quote&quot; style=&quot;margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;&quot;&gt;&lt;div&gt;Hi  there&lt;br clear=&quot;all&quot;&gt;&lt;/div&gt;&lt;div&gt;I&amp;#39;ve found some strange issue with tv while using stumpwm. tv was crashing while I was trying to load some table, so I got such output to my console:&lt;/div&gt;
&lt;div&gt;### log begins here ###&lt;/div&gt;
&lt;div&gt;=ERROR REPORT==== 22-Oct-2009::16:31:05 ===&lt;br&gt;Error in process &amp;lt;0.571.0&amp;gt; with exit value: {function_clause,[{lists,nthtail,[6,[]]},{tv_pg_gridfcns,resize_grid,3},{tv_pg,loop,1}]}&lt;br&gt;&lt;br&gt;Internal error... restarting. &lt;br&gt;

10&amp;gt;                           &lt;br&gt;=ERROR REPORT==== 22-Oct-2009::16:31:06 ===&lt;br&gt;Error in process &amp;lt;0.578.0&amp;gt; with exit value: {function_clause,[{lists,nthtail,[6,[]]},{tv_pg_gridfcns,resize_grid,3},{tv_pg,loop,1}]}&lt;br&gt;

&lt;br&gt;Internal error... restarting. &lt;/div&gt;&lt;div&gt;### log ends here ###&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;So it continued restarting over and over again. The problem was with call to lists:nthtail(6,[]) which raised exception:&lt;/div&gt;
&lt;div&gt;** exception error: no function clause matching lists:nthtail(6,[])&lt;/div&gt;&lt;div&gt;So I&amp;#39;ve made small changes to tv_pg_gridfcns.erl file. Patch attached.&lt;/div&gt;&lt;br&gt;&lt;font color=&quot;#888888&quot;&gt;-- &lt;br&gt;wbr, dym&lt;br&gt;
&lt;/font&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;br&gt;&lt;br clear=&quot;all&quot;&gt;&lt;br&gt;-- &lt;br&gt;wbr, dym&lt;br&gt;
&lt;br /&gt; &lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;tv_pg_gridfcns.erl.patch&lt;/strong&gt; (3K) &lt;a href=&quot;http://old.nabble.com/attachment/26022739/0/tv_pg_gridfcns.erl.patch&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/small-patch-for-tv-tp26010833p26022739.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26010833</id>
	<title>small patch for tv</title>
	<published>2009-10-22T07:22:38Z</published>
	<updated>2009-10-22T07:22:38Z</updated>
	<author>
		<name>Dmitriy Budashny</name>
	</author>
	<content type="html">&lt;div&gt;Hi  there&lt;br clear=&quot;all&quot;&gt;&lt;/div&gt;&lt;div&gt;I&amp;#39;ve found some strange issue with tv while using stumpwm. tv was crashing while I was trying to load some table, so I got such output to my console:&lt;/div&gt;&lt;div&gt;### log begins here ###&lt;/div&gt;
&lt;div&gt;=ERROR REPORT==== 22-Oct-2009::16:31:05 ===&lt;br&gt;Error in process &amp;lt;0.571.0&amp;gt; with exit value: {function_clause,[{lists,nthtail,[6,[]]},{tv_pg_gridfcns,resize_grid,3},{tv_pg,loop,1}]}&lt;br&gt;&lt;br&gt;Internal error... restarting. &lt;br&gt;
10&amp;gt;                           &lt;br&gt;=ERROR REPORT==== 22-Oct-2009::16:31:06 ===&lt;br&gt;Error in process &amp;lt;0.578.0&amp;gt; with exit value: {function_clause,[{lists,nthtail,[6,[]]},{tv_pg_gridfcns,resize_grid,3},{tv_pg,loop,1}]}&lt;br&gt;
&lt;br&gt;Internal error... restarting. &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;### log ends here ###&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;So it continued restarting over and over again. The problem was with call to lists:nthtail(6,[]) which raised exception:&lt;/div&gt;
&lt;div&gt;** exception error: no function clause matching lists:nthtail(6,[])&lt;/div&gt;&lt;div&gt;So I&amp;#39;ve made small changes to tv_pg_gridfcns.erl file. Patch attached.&lt;/div&gt;&lt;br&gt;-- &lt;br&gt;wbr, dym&lt;br&gt;
&lt;br /&gt; &lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;tv_pg_gridfcns.erl.patch&lt;/strong&gt; (1K) &lt;a href=&quot;http://old.nabble.com/attachment/26010833/0/tv_pg_gridfcns.erl.patch&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/small-patch-for-tv-tp26010833p26010833.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25993418</id>
	<title>Re: Patch to fix 630 English typos in documentation</title>
	<published>2009-10-21T07:15:52Z</published>
	<updated>2009-10-21T07:15:52Z</updated>
	<author>
		<name>Lars Thorsen</name>
	</author>
	<content type="html">&lt;br&gt;Hi,
&lt;br&gt;thank you for the spelling patch. We have now applied it to our 
&lt;br&gt;documentation.
&lt;br&gt;&lt;br&gt;Best regards,
&lt;br&gt;&lt;br&gt;/Lars , Erlang/OTP Ericsson
&lt;br&gt;&lt;br&gt;Badlop wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Hello,
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; The attached patch fixes 630 English spelling typos in 198 documentation files.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; It is not comprehensive. For instance, the automated spell checking
&lt;br&gt;&amp;gt; was limited to verify only lowercase words. During my manual
&lt;br&gt;&amp;gt; verification I also discarded some changes.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; The typos were originally extracted from R13B01 documentation, but
&lt;br&gt;&amp;gt; I've updated the patch to apply to R13B02, and manually verified it
&lt;br&gt;&amp;gt; again.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; ---
&lt;br&gt;&amp;gt; Badlop
&lt;br&gt;&amp;gt; ProcessOne
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; ------------------------------------------------------------------------
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;/div&gt;&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Patch-to-fix-630-English-typos-in-documentation-tp25576450p25993418.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25990326</id>
	<title>Capture stderr of spawned process</title>
	<published>2009-10-21T03:55:08Z</published>
	<updated>2009-10-21T03:55:08Z</updated>
	<author>
		<name>Max Lapshin-2</name>
	</author>
	<content type="html">This is patch, required to catch stderr of spawned process
&lt;br&gt;(tools like x264 print their status to stderr).
&lt;br&gt;&lt;br&gt;bif open_port/2 gets new flag: error  (maybe bad name?). If you pass
&lt;br&gt;it, process will receive messages {error, ErrorData}
&lt;br&gt;&lt;br&gt;Patch made for R13B02-1, not appliable for QNX because I even cannot
&lt;br&gt;imagine, how to test it.
&lt;br&gt;&lt;br&gt;Usage example:
&lt;br&gt;&lt;br&gt;Port = open_port({spawn_executable, Cmd}, [stream, {args, Args},
&lt;br&gt;{line, 1000}, error, exit_status, binary, eof]),
&lt;br&gt;&lt;br /&gt; &lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;0001-capture-stderr-of-spawned-process.patch&lt;/strong&gt; (21K) &lt;a href=&quot;http://old.nabble.com/attachment/25990326/0/0001-capture-stderr-of-spawned-process.patch&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Capture-stderr-of-spawned-process-tp25990326p25990326.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25959777</id>
	<title>Re: R13B02-1: a patch for omitting a warning on {foo, bar}:fun(args) calls</title>
	<published>2009-10-19T07:55:42Z</published>
	<updated>2009-10-19T07:55:42Z</updated>
	<author>
		<name>Yurii Rashkovskii</name>
	</author>
	<content type="html">&lt;br&gt;On 19-Oct-09, at 7:47 AM, Richard Carlsson wrote:
&lt;br&gt;&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Yurii Rashkovskii wrote:
&lt;br&gt;&amp;gt;&amp;gt; Currently erlc will spit a warning on this kind of constructs:
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; {db, &amp;quot;localhost&amp;quot;}:connect()
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; as opposed to
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; DB = {db, &amp;quot;localhost&amp;quot;},
&lt;br&gt;&amp;gt;&amp;gt; DB:connect()
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; The warning will look like:
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Warning: invalid module and/or function name; this call will always &amp;nbsp;
&lt;br&gt;&amp;gt;&amp;gt; fail
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; which is misleading, because this call will not fail (provided &amp;nbsp;
&lt;br&gt;&amp;gt;&amp;gt; modules
&lt;br&gt;&amp;gt;&amp;gt; are in place and such)
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; When you write code like the above, you are depending on how the &amp;nbsp;
&lt;br&gt;&amp;gt; current
&lt;br&gt;&amp;gt; implementation of parameterized modules works. Don't do that.
&lt;/div&gt;&lt;br&gt;I am pretty much aware of this mantra, thanks.
&lt;br&gt;&lt;br&gt;In fact, I seldom use parametrized modules per se, I am just utilizing &amp;nbsp;
&lt;br&gt;Erlang's capability to treat tuples as modules in another approach to &amp;nbsp;
&lt;br&gt;parametrized modules I built for myself.
&lt;br&gt;&lt;br&gt;Yurii.
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/R13B02-1%3A-a-patch-for-omitting-a-warning-on-%7Bfoo%2C-bar%7D%3Afun%28args%29-calls-tp25956802p25959777.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25956802</id>
	<title>R13B02-1: a patch for omitting a warning on {foo, bar}:fun(args) calls</title>
	<published>2009-10-19T04:33:06Z</published>
	<updated>2009-10-19T04:33:06Z</updated>
	<author>
		<name>Yurii Rashkovskii</name>
	</author>
	<content type="html">Hi,
&lt;br&gt;&lt;br&gt;Currently erlc will spit a warning on this kind of constructs:
&lt;br&gt;&lt;br&gt;{db, &amp;quot;localhost&amp;quot;}:connect()
&lt;br&gt;&lt;br&gt;as opposed to
&lt;br&gt;&lt;br&gt;DB = {db, &amp;quot;localhost&amp;quot;},
&lt;br&gt;DB:connect()
&lt;br&gt;&lt;br&gt;The warning will look like:
&lt;br&gt;&lt;br&gt;Warning: invalid module and/or function name; this call will always fail
&lt;br&gt;&lt;br&gt;which is misleading, because this call will not fail (provided modules &amp;nbsp;
&lt;br&gt;are in place and such)
&lt;br&gt;&lt;br&gt;Here is a proposed solution to the problem:
&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://github.com/yrashk/erlang/commit/cda6f1727965e6794aa088a200bf6c37c4586958&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://github.com/yrashk/erlang/commit/cda6f1727965e6794aa088a200bf6c37c4586958&lt;/a&gt;&lt;br&gt;&lt;br&gt;I am not sure it is perfect (hey, I am not an erlang compiler hacker, &amp;nbsp;
&lt;br&gt;as of yet), but it proved to work quite well for me.
&lt;br&gt;&lt;br&gt;Any chance it can make it to the mainstream in some way?
&lt;br&gt;&lt;br&gt;Thanks,
&lt;br&gt;Yurii.
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/R13B02-1%3A-a-patch-for-omitting-a-warning-on-%7Bfoo%2C-bar%7D%3Afun%28args%29-calls-tp25956802p25956802.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25954716</id>
	<title>Bugs in httpc timeout and keep-alive queue handling</title>
	<published>2009-10-19T01:17:54Z</published>
	<updated>2009-10-19T01:17:54Z</updated>
	<author>
		<name>Jean-Sébastien Pédron-4</name>
	</author>
	<content type="html">-----BEGIN PGP SIGNED MESSAGE-----
&lt;br&gt;Hash: SHA1
&lt;br&gt;&lt;br&gt;Hello,
&lt;br&gt;&lt;br&gt;Attached is a patch against R13B02-1 that fixes two bugs in
&lt;br&gt;httpc_handler.erl.
&lt;br&gt;&lt;br&gt;The first part fixes a bug with request timeout. When a queued request
&lt;br&gt;(ie. not the active one in #state.request) times out, the error is sent
&lt;br&gt;to the process associated with the active request. If I understand the
&lt;br&gt;problem correctly, this means that this process could receive the
&lt;br&gt;timeout error and the HTTP response, but the process for which the
&lt;br&gt;request timed out won't receive anything.
&lt;br&gt;&lt;br&gt;The second part fixes a bug with the keep-alive queue: in terminate/2,
&lt;br&gt;the requests in this queue are &amp;quot;forgotten&amp;quot;. With the patch, the
&lt;br&gt;keep-alive queue is treated like the pipeline queue.
&lt;br&gt;&lt;br&gt;The third part adds a clause to the retry_pipline/2 function to not
&lt;br&gt;retry timed out requests.
&lt;br&gt;&lt;br&gt;With this patch, I couldn't hang httpc with multiple concurrent requests
&lt;br&gt;to the same URL (a slow webservice). The handle_info/2 clause printing a
&lt;br&gt;warning about unexpected received data isn't triggered anymore (it was
&lt;br&gt;added in R13B02).
&lt;br&gt;&lt;br&gt;- --
&lt;br&gt;Jean-Sébastien Pédron
&lt;br&gt;&lt;a href=&quot;http://www.dumbbell.fr/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.dumbbell.fr/&lt;/a&gt;&lt;br&gt;&lt;br&gt;PGP Key: &lt;a href=&quot;http://www.dumbbell.fr/pgp/pubkey.asc&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.dumbbell.fr/pgp/pubkey.asc&lt;/a&gt;&lt;br&gt;-----BEGIN PGP SIGNATURE-----
&lt;br&gt;Version: GnuPG v1.4.10 (FreeBSD)
&lt;br&gt;Comment: Using GnuPG with Mozilla - &lt;a href=&quot;http://enigmail.mozdev.org&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://enigmail.mozdev.org&lt;/a&gt;&lt;br&gt;&lt;br&gt;iEYEARECAAYFAkrcILIACgkQa+xGJsFYOlPy+ACeNJMIIkKBUaOH7+r7FYBKgSpG
&lt;br&gt;C94AoIvGUW4NLh/FjjorTYJJxLVEFjiy
&lt;br&gt;=D7JD
&lt;br&gt;-----END PGP SIGNATURE-----
&lt;br&gt;&lt;br /&gt;--- otp_src_R13B02-1.orig/lib/inets/src/http_client/httpc_handler.erl	2009-09-18 16:12:59.000000000 +0200
&lt;br&gt;+++ otp_src_R13B02-1/lib/inets/src/http_client/httpc_handler.erl	2009-10-14 09:22:46.000000000 +0200
&lt;br&gt;@@ -505,10 +505,25 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{stop, normal, 
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; State#state{canceled = [RequestId | State#state.canceled],
&lt;br&gt;&amp;nbsp;		 request = Request#request{from = answer_sent}}};
&lt;br&gt;-handle_info({timeout, RequestId}, State = #state{request = Request}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;httpc_response:send(Request#request.from, 
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp; &amp;nbsp; httpc_response:error(Request,timeout)),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;{noreply, State#state{canceled = [RequestId | State#state.canceled]}};
&lt;br&gt;+handle_info({timeout, RequestId}, State) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Fun = fun
&lt;br&gt;+	(#request{id = Id} = Request) when Id == RequestId -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;httpc_response:send(Request#request.from,
&lt;br&gt;+				httpc_response:error(Request,timeout)),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;[Request#request{from = answer_sent}];
&lt;br&gt;+	(_) -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;true
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case State#state.status of
&lt;br&gt;+	pipeline -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;Pipeline = queue:filter(Fun, State#state.pipeline),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{noreply, State#state{canceled = [RequestId | State#state.canceled],
&lt;br&gt;+				 &amp;nbsp;pipeline = Pipeline}};
&lt;br&gt;+	keep_alive -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;KeepAlive = queue:filter(Fun, State#state.keep_alive),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{noreply, State#state{canceled = [RequestId | State#state.canceled],
&lt;br&gt;+				 &amp;nbsp;keep_alive = KeepAlive}}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;handle_info(timeout_queue, State = #state{request = undefined}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{stop, normal, State};
&lt;br&gt;@@ -588,6 +603,12 @@
&lt;br&gt;&amp;nbsp;	true -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;ok
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case queue:is_empty(State#state.keep_alive) of 
&lt;br&gt;+	false -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;retry_pipline(queue:to_list(State#state.keep_alive), State);
&lt;br&gt;+	true -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;ok
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;cancel_timer(Timers#timers.queue_timer, timeout_queue),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Socket = Session#tcp_session.socket, 
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;http_transport:close(socket_type(Session#tcp_session.scheme), Socket);
&lt;br&gt;@@ -1191,6 +1212,8 @@
&lt;br&gt;&amp;nbsp;retry_pipline([], _) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+retry_pipline([#request{from = answer_sent}|PipeLine], State) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;retry_pipline(PipeLine, State);
&lt;br&gt;&amp;nbsp;retry_pipline([Request |PipeLine], &amp;nbsp;State = 
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp; &amp;nbsp;#state{timers = Timers, profile_name = ProfileName}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;NewState =
&lt;br&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Bugs-in-httpc-timeout-and-keep-alive-queue-handling-tp25954716p25954716.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25944467</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in  get_diagnos function</title>
	<published>2009-10-18T00:06:44Z</published>
	<updated>2009-10-18T00:06:44Z</updated>
	<author>
		<name>Juhani Ränkimies-2</name>
	</author>
	<content type="html">On Mon, Oct 12, 2009 at 11:33 PM, Juhani Ränkimies &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25944467&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;juhani@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt; On 10/11/09, Andrew Thompson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25944467&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;andrew@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Ah, that does sound like a similar issue although I'm not sure my patch
&lt;br&gt;&amp;gt;&amp;gt; will solve it. Does it happen consistantly or is it random? Are you
&lt;br&gt;&amp;gt;&amp;gt; using parameterized queries?
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; it now. I'll try to find time to reproduce it on weekend.
&lt;br&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;Yes, I'm using param_query.
&lt;br&gt;&lt;br&gt;I wasn't able to reproduce the problem at this time.
&lt;br&gt;I couldn't use the environment where I observed the problem and the
&lt;br&gt;test setup has at least these differences:
&lt;br&gt;- newer version of erlang
&lt;br&gt;- newer versions of sql server and drivers
&lt;br&gt;- it's is not patched to support unicode strings
&lt;br&gt;- my tests were light, so if it occurs rarely I might not have caught it
&lt;br&gt;&lt;br&gt;next week i'll drop my workaround for {error,&amp;quot;No SQL-driver
&lt;br&gt;information available.&amp;quot;} from couple of places and see what happens.
&lt;br&gt;&lt;br&gt;&amp;gt; Juhani
&lt;br&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25944467.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25927172</id>
	<title>Re: Epp Bugfix and macros overloading</title>
	<published>2009-10-16T08:16:46Z</published>
	<updated>2009-10-16T08:16:46Z</updated>
	<author>
		<name>Christopher Faulet</name>
	</author>
	<content type="html">Robert Virding a écrit :
&lt;div class='shrinkable-quote'&gt;&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; I rather like this extension, it is something I always meant to do but never
&lt;br&gt;&amp;gt; got around to doing.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; I am not sure, though, that I completely agree with how you choose which
&lt;br&gt;&amp;gt; definition to use, especially the third case here which I think should give
&lt;br&gt;&amp;gt; an undefined macro error. My reasoning is that if you define a macro to have
&lt;br&gt;&amp;gt; arguments, one or many definitions, and call it with arguments, even with an
&lt;br&gt;&amp;gt; empty argument list then you should only try for the matching definition and
&lt;br&gt;&amp;gt; not take the one without arguments. So if:
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; -define(M, a).
&lt;br&gt;&amp;gt; -define(M(), b).
&lt;br&gt;&amp;gt; -define(M(X,Y), {X,Y}).
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; then
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; ?M &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- should use 1st def
&lt;br&gt;&amp;gt; ?M() &amp;nbsp; &amp;nbsp; - should use 2nd def
&lt;br&gt;&amp;gt; ?M(a,b) - should use 3rd def
&lt;br&gt;&amp;gt; ?M(a) &amp;nbsp; - should generate an error
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; However if only:
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; -define(M, a).
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; then all calls will use this definition.
&lt;br&gt;&amp;gt; 
&lt;/div&gt;&lt;/div&gt;Hi Robert,
&lt;br&gt;&lt;br&gt;Thanks for your comments. You are probably right. Your solution is less
&lt;br&gt;error prone and avoids ambiguities.
&lt;br&gt;&lt;br&gt;I made a new patch that takes your suggestion into account. I also
&lt;br&gt;modified some errors to be more precise in diagnostics.
&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;Christopher Faulet &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25927172&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;christopher.faulet@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br /&gt;--- lib/stdlib/src/epp.erl.orig	2009-10-16 14:11:07.000000000 +0200
&lt;br&gt;+++ lib/stdlib/src/epp.erl	2009-10-16 16:28:14.000000000 +0200
&lt;br&gt;@@ -99,18 +99,24 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;badly formed '~s'&amp;quot;, [W]);
&lt;br&gt;&amp;nbsp;format_error({call,What}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;illegal macro call '~s'&amp;quot;,[What]);
&lt;br&gt;-format_error({undefined,M}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;undefined macro '~w'&amp;quot;, [M]);
&lt;br&gt;+format_error({undefined,M,none}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;undefined macro '~s'&amp;quot;, [M]);
&lt;br&gt;+format_error({undefined,M,A}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;undefined macro '~s/~p'&amp;quot;, [M,A]);
&lt;br&gt;&amp;nbsp;format_error({depth,What}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;~s too deep&amp;quot;,[What]);
&lt;br&gt;&amp;nbsp;format_error({mismatch,M}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;argument mismatch for macro '~w'&amp;quot;, [M]);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;argument mismatch for macro '~s'&amp;quot;, [M]);
&lt;br&gt;&amp;nbsp;format_error({arg_error,M}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;badly formed argument for macro '~w'&amp;quot;, [M]);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;badly formed argument for macro '~s'&amp;quot;, [M]);
&lt;br&gt;&amp;nbsp;format_error({redefine,M}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;redefining macro '~w'&amp;quot;, [M]);
&lt;br&gt;-format_error({circular,M}) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;circular macro '~w'&amp;quot;, [M]);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;redefining macro '~s'&amp;quot;, [M]);
&lt;br&gt;+format_error({redefine_predef,M}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;redefining predefined macro '~s'&amp;quot;, [M]);
&lt;br&gt;+format_error({circular,M,none}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;circular macro '~s'&amp;quot;, [M]);
&lt;br&gt;+format_error({circular,M,A}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;circular macro '~s/~p'&amp;quot;, [M,A]);
&lt;br&gt;&amp;nbsp;format_error({include,W,F}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;io_lib:format(&amp;quot;can't find include ~s \&amp;quot;~s\&amp;quot;&amp;quot;, [W,F]);
&lt;br&gt;&amp;nbsp;format_error({illegal,How,What}) -&amp;gt;
&lt;br&gt;@@ -240,18 +246,23 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms));
&lt;br&gt;&amp;nbsp;user_predef([{M,Val}|Pdm], Ms) when is_atom(M) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, Ms) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;+	{ok,_Defs} when is_list(_Defs) -&amp;gt; %% User defined macros
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{error,{redefine,M}};
&lt;br&gt;+	{ok,_Def} -&amp;gt; %% Predefined macros
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{error,{redefine_predef,M}};
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;Exp = erl_parse:tokens(erl_parse:abstract(Val)),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms))
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;user_predef([M|Pdm], Ms) when is_atom(M) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, Ms) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;+	{ok,_Defs} when is_list(_Defs) -&amp;gt; %% User defined macros
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{error,{redefine,M}};
&lt;br&gt;+	{ok,_Def} -&amp;gt; %% Predefined macros
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{error,{redefine_predef,M}};
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, {none,[{atom,1,true}]}, Ms))
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;user_predef(Pdm,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;dict:store({atom,M}, [{none, {none,[{atom,1,true}]}}], Ms))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;user_predef([Md|_Pdm], _Ms) -&amp;gt; {error,{bad,Md}};
&lt;br&gt;&amp;nbsp;user_predef([], Ms) -&amp;gt; {ok,Ms}.
&lt;br&gt;@@ -458,57 +469,55 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% scan_define(Tokens, DefineToken, From, EppState)
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) -&amp;gt;
&lt;br&gt;+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St)
&lt;br&gt;+ &amp;nbsp;when Type =:= atom; Type =:= var -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_OldDef} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {none,macro_expansion(Toks)})
&lt;br&gt;+ 	 &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% User defined macros: can be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case proplists:is_defined(none, Defs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;true -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;false -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {none, {none,macro_expansion(Toks)}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, _PreDef} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% Predefined macros: cannot be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {none, {none,macro_expansion(Toks)}})
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;-		{ok, {As, Me}} -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp;{atom, M},
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp;{As, Me});
&lt;br&gt;-		_ -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;end
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_OldDef} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {none,macro_expansion(Toks)})
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;-		{ok, {As, Me}} -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp; {As, Me});
&lt;br&gt;-		_ -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;end
&lt;br&gt;+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
&lt;br&gt;+ &amp;nbsp;when Type =:= atom; Type =:= var -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, {As,Me}} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Len = length(As),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% User defined macros: can be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case proplists:is_defined(Len, Defs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;true -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;false -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St, {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {Len, {As, Me}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, _PreDef} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% Predefined macros: cannot be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_ -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;scan_define(_Toks, Def, From, St) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;@@ -523,13 +532,17 @@
&lt;br&gt;&amp;nbsp;%%% the information from St#epp.uses is traversed, and if a circularity
&lt;br&gt;&amp;nbsp;%%% is detected, an error message is thrown.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-scan_define_cont(F, St, M, Def) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;Ms = dict:store(M, Def, St#epp.macs),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;U = dict:store(M, macro_uses(Def), St#epp.uses),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(F, St#epp{uses=U, macs=Ms}).
&lt;br&gt;+scan_define_cont(F, St, M, {Arity, Def}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;try
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;U = dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_toks(F, St#epp{uses=U, macs=Ms})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;catch
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_:{error, Line, Reason} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(F, {error,{Line,epp,Reason}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-macro_uses(undefined) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;undefined;
&lt;br&gt;&amp;nbsp;macro_uses({_Args, Tokens}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Uses0 = macro_ref(Tokens),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;lists:usort(Uses0).
&lt;br&gt;@@ -538,31 +551,25 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;[];
&lt;br&gt;&amp;nbsp;macro_ref([{'?', _}, {'?', _} | Rest]) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;macro_ref(Rest);
&lt;br&gt;-macro_ref([{'?', _}, {atom, _, A} | Rest]) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;[{atom, A} | macro_ref(Rest)];
&lt;br&gt;-macro_ref([{'?', _}, {var, _, A} | Rest]) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;[{atom, A} | macro_ref(Rest)];
&lt;br&gt;+macro_ref([{'?', _}, {atom, Lm, A} | Rest]) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Arity = count_args(Rest, Lm, A),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;[{{atom, A}, Arity} | macro_ref(Rest)];
&lt;br&gt;+macro_ref([{'?', _}, {var, Lm, A} | Rest]) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Arity = count_args(Rest, Lm, A),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;[{{atom, A}, Arity} | macro_ref(Rest)];
&lt;br&gt;&amp;nbsp;macro_ref([_Token | Rest]) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;macro_ref(Rest).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-all_macro_uses(D0) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;L = dict:to_list(D0),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;D = dict:new(),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;add_macro_uses(L, D).
&lt;br&gt;-
&lt;br&gt;-add_macro_uses([], D) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;D;
&lt;br&gt;-add_macro_uses([{Key, Def} | Rest], D0) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;add_macro_uses(Rest, dict:store(Key, macro_uses(Def), D0)).
&lt;br&gt;-
&lt;br&gt;&amp;nbsp;%% scan_undef(Tokens, UndefToken, From, EppState)
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Uses = dict:erase({atom,M}, St#epp.uses),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=Uses});
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Uses = dict:erase({atom,M}, St#epp.uses),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=Uses});
&lt;br&gt;&amp;nbsp;scan_undef(_Toks, Undef, From, St) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St).
&lt;br&gt;@@ -801,42 +808,55 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;%% (Type will always be 'atom')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{Ms, U} = Ms0,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Lm = loc(MacT),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;check_uses([{Type,M}], [], U, Lm),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Tinfo = element(2, MacT),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({Type,M}, Ms) of
&lt;br&gt;-	{ok,{none,Exp}} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;expand_macros(expand_macro(Exp, Tinfo, Toks, dict:new()), Ms0);
&lt;br&gt;-	{ok,{As,Exp}} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case expand_macro1(Type, Lm, M, Toks, Ms) of
&lt;br&gt;+	{ok, {none,Exp}} -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;check_uses([{{Type,M}, none}], [], U, Lm),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;expand_macros(Toks1++Toks, Ms0);
&lt;br&gt;+	{ok, {As,Exp}} -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;check_uses([{{Type,M}, length(As)}], [], U, Lm),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;%%io:format(&amp;quot;Bound arguments to macro ~w (~w)~n&amp;quot;, [M,Bs]),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0);
&lt;br&gt;-	{ok,undefined} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M}});
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M}})
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;+
&lt;br&gt;+expand_macro1(Type, Lm, M, Toks, Ms) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Arity = count_args(Toks, Lm, M),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case dict:find({Type,M}, Ms) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, [{none, Def}]} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Def};
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case proplists:get_value(Arity, Defs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;undefined -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M,Arity}});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Def -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Def}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, PreDef} -&amp;gt; %% Predefined macro
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, PreDef};
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M,Arity}})
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-check_uses(undefined, _Anc, _U, _Lm) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;&amp;nbsp;check_uses([], _Anc, _U, _Lm) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;&amp;nbsp;check_uses([M|Rest], Anc, U, Lm) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case lists:member(M, Anc) of
&lt;br&gt;&amp;nbsp;	true -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;{_, Name} = M,
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{circular,Name}});
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{{_, Name},Arity} = M,
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{circular,Name,Arity}});
&lt;br&gt;&amp;nbsp;	false -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;L = get_macro_uses(M, U),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;check_uses(L, [M|Anc], U, Lm),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;check_uses(Rest, Anc, U, Lm)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;-get_macro_uses(M, U) -&amp;gt;
&lt;br&gt;+
&lt;br&gt;+get_macro_uses({M,Arity}, U) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find(M, U) of
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;[];
&lt;br&gt;&amp;nbsp;	{ok, L} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;L
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;proplists:get_value(Arity, L, proplists:get_value(none, L, []))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% Macro expansion
&lt;br&gt;@@ -889,6 +909,30 @@
&lt;br&gt;&amp;nbsp;store_arg(_L, _M, A, Arg, Bs) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;dict:store(A, Arg, Bs).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+%% count_args(Tokens, MacroLine, MacroName)
&lt;br&gt;+%% &amp;nbsp;Count the number of arguments in a macro call.
&lt;br&gt;+count_args([{'(', _Llp},{')',_Lrp}|_Toks], _Lm, _M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;0;
&lt;br&gt;+count_args([{'(', _Llp},{',',_Lc}|_Toks], Lm, M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{arg_error,M}});
&lt;br&gt;+count_args([{'(',_Llp}|Toks0], Lm, M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{_Arg,Toks1} = macro_arg(Toks0, [], []),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;count_args(Toks1, Lm, M, 1);
&lt;br&gt;+count_args(_Toks, _Lm, _M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;none.
&lt;br&gt;+
&lt;br&gt;+count_args([{')',_Lrp}|_Toks], _Lm, _M, NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;NbArgs;
&lt;br&gt;+count_args([{',',_Lc},{')',_Lrp}|_Toks], Lm, M, _NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{arg_error,M}});
&lt;br&gt;+count_args([{',',_Lc}|Toks0], Lm, M, NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{_Arg,Toks1} = macro_arg(Toks0, [], []),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;count_args(Toks1, Lm, M, NbArgs+1);
&lt;br&gt;+count_args([], Lm, M, _NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{arg_error,M}});
&lt;br&gt;+count_args(_Toks, Lm, M, _NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{mismatch,M}}).
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;%% macro_arg([Tok], [ClosePar], [ArgTok]) -&amp;gt; {[ArgTok],[RestTok]}.
&lt;br&gt;&amp;nbsp;%% &amp;nbsp;Collect argument tokens until we hit a ',' or a ')'. We know a
&lt;br&gt;&amp;nbsp;%% &amp;nbsp;enough about syntax to recognise &amp;quot;open parentheses&amp;quot; and keep
&lt;br&gt;&lt;br /&gt; &lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;signature.asc&lt;/strong&gt; (268 bytes) &lt;a href=&quot;http://old.nabble.com/attachment/25927172/0/signature.asc&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Epp-Bugfix-and-macros-overloading-tp25822198p25927172.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25917385</id>
	<title>Re: Epp Bugfix and macros overloading</title>
	<published>2009-10-15T15:55:30Z</published>
	<updated>2009-10-15T15:55:30Z</updated>
	<author>
		<name>Robert Virding</name>
	</author>
	<content type="html">2009/10/9 christopher faulet &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25917385&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;christopher.faulet@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Hi all,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Here are two patches for the module epp in R13B02-1.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; * The second patch includes the first one and adds support of multiple
&lt;br&gt;&amp;gt; definitions for macros in the module epp (i.e. with the same name but
&lt;br&gt;&amp;gt; with different arities). This feature wouldn't break any code (I hope so
&lt;br&gt;&amp;gt; :) and might be usefull.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Here is an simple example that uses it:
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; =============================
&lt;br&gt;&amp;gt; -module(test).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; -export([test/0]).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; -define(MY_MACRO(), &amp;nbsp; &amp;nbsp;foo).
&lt;br&gt;&amp;gt; -define(MY_MACRO, &amp;nbsp; &amp;nbsp; &amp;nbsp;bar).
&lt;br&gt;&amp;gt; -define(MY_MACRO(X,Y), {X, Y}).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; test() -&amp;gt; &amp;nbsp;%% return [bar, foo, foo, {foo, bar}]
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp;[
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; ?MY_MACRO, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% use the 2nd def, replaced by bar
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; ?MY_MACRO(), &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% use the 1st def, replaced by foo
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; ?MY_MACRO(foo), &amp;nbsp; &amp;nbsp; %% use the 2nd def, replaced by bar(foo)
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; ?MY_MACRO(foo, bar) %% use the 3rd def, replaced by {foo,bar}
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp;].
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; bar(X) -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp;X.
&lt;br&gt;&amp;gt; =============================
&lt;br&gt;&amp;gt;
&lt;/div&gt;&lt;br&gt;I rather like this extension, it is something I always meant to do but never
&lt;br&gt;got around to doing.
&lt;br&gt;&lt;br&gt;I am not sure, though, that I completely agree with how you choose which
&lt;br&gt;definition to use, especially the third case here which I think should give
&lt;br&gt;an undefined macro error. My reasoning is that if you define a macro to have
&lt;br&gt;arguments, one or many definitions, and call it with arguments, even with an
&lt;br&gt;empty argument list then you should only try for the matching definition and
&lt;br&gt;not take the one without arguments. So if:
&lt;br&gt;&lt;br&gt;-define(M, a).
&lt;br&gt;-define(M(), b).
&lt;br&gt;-define(M(X,Y), {X,Y}).
&lt;br&gt;&lt;br&gt;then
&lt;br&gt;&lt;br&gt;?M &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- should use 1st def
&lt;br&gt;?M() &amp;nbsp; &amp;nbsp; - should use 2nd def
&lt;br&gt;?M(a,b) - should use 3rd def
&lt;br&gt;?M(a) &amp;nbsp; - should generate an error
&lt;br&gt;&lt;br&gt;However if only:
&lt;br&gt;&lt;br&gt;-define(M, a).
&lt;br&gt;&lt;br&gt;then all calls will use this definition.
&lt;br&gt;&lt;br&gt;Robert
&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Epp-Bugfix-and-macros-overloading-tp25822198p25917385.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25892053</id>
	<title>Re: wxe_server bug? (and patch)</title>
	<published>2009-10-14T07:23:00Z</published>
	<updated>2009-10-14T07:23:00Z</updated>
	<author>
		<name>Dan Gudmundsson</name>
	</author>
	<content type="html">Mazen Harake wrote:
&lt;br&gt;&amp;gt; Yeah I can see how using pids are useful but the semantic difference is
&lt;br&gt;&amp;gt; that you can't really get the pid from somewhere unless you register it?
&lt;br&gt;&amp;gt; I mean the return value is a wxWindow() type. I dunno... just a thought :)
&lt;br&gt;&lt;br&gt;wx_object:get_pid(Ref).
&lt;br&gt;&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; Waiting patiently to learn the right way ;)
&lt;br&gt;&lt;br&gt;The right way is to not use term_to_binary(self()) when registrering the process
&lt;br&gt;with the driver, because that representation changes when the node becomes distributed.
&lt;br&gt;&lt;br&gt;I.e. more code and changes in the driver, but better, nicer and uses less memory,
&lt;br&gt;that code wasn't the best I have written :-)
&lt;br&gt;&lt;br&gt;/Dan
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; Dan Gudmundsson wrote:
&lt;br&gt;&amp;gt;&amp;gt; I'll fix the problem, in the right way(tm).
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; /Dan
&lt;br&gt;&amp;gt;&amp;gt; PS: I just applied your wx_object patch but I allowed pids as well as
&lt;br&gt;&amp;gt;&amp;gt; registered names and
&lt;br&gt;&amp;gt;&amp;gt; added wx_object:cast/2.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; On Wed, Oct 14, 2009 at 3:25 PM, Mazen Harake
&lt;br&gt;&amp;gt;&amp;gt; &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25892053&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;mazen.harake@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt;&amp;gt; &amp;nbsp;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; A quick note:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; I just realized that this example doesn't work unless you have
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; applied my
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; previous patch for wx_object.erl. Either apply that or change the
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; code to
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; call the wx_object with the form (somehow) :)
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Mazen Harake wrote:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Hi,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; There is a situation in the wx library that causes the wxe_server to
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; crash
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; when it receives a message with a pid which is considered by
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; distributed
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Erlang to come from another node when in fact it isn't. This happens
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; when
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; net_kernel is started explicitly (I.e. Erlang going into
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; distribution mode)
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; and an wx_object (which was created before net_kernel was started) is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; destroyed.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Here is a simple example:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Create this module:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; -module(test).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; -compile(export_all).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; start() -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx:new(),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx_object:start_link({local, ?MODULE}, ?MODULE, wx:get_env(), []).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; close(_, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx_object:call(?MODULE, stop).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; init(Wx) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx:set_env(Wx),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;Mf = wxFrame:new(wx:null(),1,&amp;quot;&amp;quot;,[{size,{300,300}}]),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:show(Mf),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:connect(Mf, close_window, [{callback, fun ?MODULE:close/2}]),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{Mf, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; handle_call(stop, _From, Mf) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:destroy(Mf),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{stop, normal, ok, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; terminate(normal, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;ok.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Then run this in the shell:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Eshell V5.7.1 &amp;nbsp;(abort with ^G)
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 1&amp;gt; c(test).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; {ok,test}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 2&amp;gt; test:start().
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; {wx_ref,35,wxFrame,&amp;lt;0.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 3&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; This should give you a small frame, don't close it yet,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Now do this:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 3&amp;gt; net_kernel:start([bad,shortnames]).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; {ok,&amp;lt;0.49.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; (bad@prestine)4&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Now close the frame and you should see:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; =ERROR REPORT==== 14-Oct-2009::13:17:08 ===
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ** Generic server &amp;lt;0.39.0&amp;gt; terminating
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ** Last message in was {'_wxe_destroy_',&amp;lt;3.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ** When Server state == {state,#Port&amp;lt;0.2605&amp;gt;,#Port&amp;lt;0.2602&amp;gt;,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{1,{&amp;lt;0.32.0&amp;gt;,{user,[],[],undefined},nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[&amp;lt;0.57.0&amp;gt;],
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{1,{#Fun&amp;lt;test.close.2&amp;gt;,1,nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ** Reason for termination ==
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ** {badarg,[{erlang,is_process_alive,[&amp;lt;3.42.0&amp;gt;]},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {wxe_server,handle_info,2},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {gen_server,handle_msg,5},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {proc_lib,init_p_do_apply,3}]}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; The pid which comes from the port is not recognized as a local pid and
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; thus erlang:is_process_alive/1 will exit with badarg. My question
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; is: Is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; this a &amp;quot;feature&amp;quot; or a bug? I think this is a bug but I'm not sure
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; what is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; expected from the wx library point of view. IMHO it shouldn't crash
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; and just
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ignore it in this case because the wxe_server shouldn't be allowed
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; to crash.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Anyway I put in a patch as well just in case this is something that
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; should
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; be fixed. The patch can be applied to both wx 0.98.1 and 0.98.3.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Cheers,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ------------------------------------------------------------------------
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; 
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt; 
&lt;/div&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wxe_server-bug--%28and-patch%29-tp25890987p25892053.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25891875</id>
	<title>Re: wxe_server bug? (and patch)</title>
	<published>2009-10-14T07:13:15Z</published>
	<updated>2009-10-14T07:13:15Z</updated>
	<author>
		<name>Mazen Harake-2</name>
	</author>
	<content type="html">Yeah I can see how using pids are useful but the semantic difference is 
&lt;br&gt;that you can't really get the pid from somewhere unless you register it? 
&lt;br&gt;I mean the return value is a wxWindow() type. I dunno... just a thought :)
&lt;br&gt;&lt;br&gt;Waiting patiently to learn the right way ;)
&lt;br&gt;&lt;br&gt;/Mazen
&lt;br&gt;&lt;br&gt;Dan Gudmundsson wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; I'll fix the problem, in the right way(tm).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; /Dan
&lt;br&gt;&amp;gt; PS: I just applied your wx_object patch but I allowed pids as well as
&lt;br&gt;&amp;gt; registered names and
&lt;br&gt;&amp;gt; added wx_object:cast/2.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; On Wed, Oct 14, 2009 at 3:25 PM, Mazen Harake
&lt;br&gt;&amp;gt; &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25891875&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;mazen.harake@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt; &amp;nbsp; 
&lt;br&gt;&amp;gt;&amp;gt; A quick note:
&lt;br&gt;&amp;gt;&amp;gt; I just realized that this example doesn't work unless you have applied my
&lt;br&gt;&amp;gt;&amp;gt; previous patch for wx_object.erl. Either apply that or change the code to
&lt;br&gt;&amp;gt;&amp;gt; call the wx_object with the form (somehow) :)
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Mazen Harake wrote:
&lt;br&gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; 
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Hi,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; There is a situation in the wx library that causes the wxe_server to crash
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; when it receives a message with a pid which is considered by distributed
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Erlang to come from another node when in fact it isn't. This happens when
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; net_kernel is started explicitly (I.e. Erlang going into distribution mode)
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; and an wx_object (which was created before net_kernel was started) is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; destroyed.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Here is a simple example:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Create this module:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; -module(test).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; -compile(export_all).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; start() -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx:new(),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx_object:start_link({local, ?MODULE}, ?MODULE, wx:get_env(), []).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; close(_, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx_object:call(?MODULE, stop).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; init(Wx) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wx:set_env(Wx),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;Mf = wxFrame:new(wx:null(),1,&amp;quot;&amp;quot;,[{size,{300,300}}]),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:show(Mf),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:connect(Mf, close_window, [{callback, fun ?MODULE:close/2}]),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{Mf, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; handle_call(stop, _From, Mf) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;wxFrame:destroy(Mf),
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{stop, normal, ok, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; terminate(normal, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;ok.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Then run this in the shell:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Eshell V5.7.1 &amp;nbsp;(abort with ^G)
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; 1&amp;gt; c(test).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; {ok,test}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; 2&amp;gt; test:start().
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; {wx_ref,35,wxFrame,&amp;lt;0.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; 3&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; This should give you a small frame, don't close it yet,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Now do this:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; 3&amp;gt; net_kernel:start([bad,shortnames]).
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; {ok,&amp;lt;0.49.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; (bad@prestine)4&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Now close the frame and you should see:
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; =ERROR REPORT==== 14-Oct-2009::13:17:08 ===
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ** Generic server &amp;lt;0.39.0&amp;gt; terminating
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ** Last message in was {'_wxe_destroy_',&amp;lt;3.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ** When Server state == {state,#Port&amp;lt;0.2605&amp;gt;,#Port&amp;lt;0.2602&amp;gt;,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp;{1,{&amp;lt;0.32.0&amp;gt;,{user,[],[],undefined},nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[&amp;lt;0.57.0&amp;gt;],
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{1,{#Fun&amp;lt;test.close.2&amp;gt;,1,nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ** Reason for termination ==
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ** {badarg,[{erlang,is_process_alive,[&amp;lt;3.42.0&amp;gt;]},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {wxe_server,handle_info,2},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {gen_server,handle_msg,5},
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {proc_lib,init_p_do_apply,3}]}
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; The pid which comes from the port is not recognized as a local pid and
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; thus erlang:is_process_alive/1 will exit with badarg. My question is: Is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; this a &amp;quot;feature&amp;quot; or a bug? I think this is a bug but I'm not sure what is
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; expected from the wx library point of view. IMHO it shouldn't crash and just
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ignore it in this case because the wxe_server shouldn't be allowed to crash.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Anyway I put in a patch as well just in case this is something that should
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; be fixed. The patch can be applied to both wx 0.98.1 and 0.98.3.
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; Cheers,
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ------------------------------------------------------------------------
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; 
&lt;br&gt;&amp;gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; &amp;nbsp; &amp;nbsp; 
&lt;/div&gt;&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wxe_server-bug--%28and-patch%29-tp25890987p25891875.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25891504</id>
	<title>Re: wxe_server bug? (and patch)</title>
	<published>2009-10-14T06:52:16Z</published>
	<updated>2009-10-14T06:52:16Z</updated>
	<author>
		<name>Dan Gudmundsson</name>
	</author>
	<content type="html">I'll fix the problem, in the right way(tm).
&lt;br&gt;&lt;br&gt;/Dan
&lt;br&gt;PS: I just applied your wx_object patch but I allowed pids as well as
&lt;br&gt;registered names and
&lt;br&gt;added wx_object:cast/2.
&lt;br&gt;&lt;br&gt;On Wed, Oct 14, 2009 at 3:25 PM, Mazen Harake
&lt;br&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25891504&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;mazen.harake@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; A quick note:
&lt;br&gt;&amp;gt; I just realized that this example doesn't work unless you have applied my
&lt;br&gt;&amp;gt; previous patch for wx_object.erl. Either apply that or change the code to
&lt;br&gt;&amp;gt; call the wx_object with the form (somehow) :)
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Mazen Harake wrote:
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Hi,
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; There is a situation in the wx library that causes the wxe_server to crash
&lt;br&gt;&amp;gt;&amp;gt; when it receives a message with a pid which is considered by distributed
&lt;br&gt;&amp;gt;&amp;gt; Erlang to come from another node when in fact it isn't. This happens when
&lt;br&gt;&amp;gt;&amp;gt; net_kernel is started explicitly (I.e. Erlang going into distribution mode)
&lt;br&gt;&amp;gt;&amp;gt; and an wx_object (which was created before net_kernel was started) is
&lt;br&gt;&amp;gt;&amp;gt; destroyed.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Here is a simple example:
&lt;br&gt;&amp;gt;&amp;gt; Create this module:
&lt;br&gt;&amp;gt;&amp;gt; -module(test).
&lt;br&gt;&amp;gt;&amp;gt; -compile(export_all).
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; start() -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  wx:new(),
&lt;br&gt;&amp;gt;&amp;gt;  wx_object:start_link({local, ?MODULE}, ?MODULE, wx:get_env(), []).
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; close(_, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  wx_object:call(?MODULE, stop).
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; init(Wx) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  wx:set_env(Wx),
&lt;br&gt;&amp;gt;&amp;gt;  Mf = wxFrame:new(wx:null(),1,&amp;quot;&amp;quot;,[{size,{300,300}}]),
&lt;br&gt;&amp;gt;&amp;gt;  wxFrame:show(Mf),
&lt;br&gt;&amp;gt;&amp;gt;  wxFrame:connect(Mf, close_window, [{callback, fun ?MODULE:close/2}]),
&lt;br&gt;&amp;gt;&amp;gt;  {Mf, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; handle_call(stop, _From, Mf) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  wxFrame:destroy(Mf),
&lt;br&gt;&amp;gt;&amp;gt;  {stop, normal, ok, Mf}.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; terminate(normal, _) -&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  ok.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Then run this in the shell:
&lt;br&gt;&amp;gt;&amp;gt; Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Eshell V5.7.1  (abort with ^G)
&lt;br&gt;&amp;gt;&amp;gt; 1&amp;gt; c(test).
&lt;br&gt;&amp;gt;&amp;gt; {ok,test}
&lt;br&gt;&amp;gt;&amp;gt; 2&amp;gt; test:start().
&lt;br&gt;&amp;gt;&amp;gt; {wx_ref,35,wxFrame,&amp;lt;0.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt; 3&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; This should give you a small frame, don't close it yet,
&lt;br&gt;&amp;gt;&amp;gt; Now do this:
&lt;br&gt;&amp;gt;&amp;gt; 3&amp;gt; net_kernel:start([bad,shortnames]).
&lt;br&gt;&amp;gt;&amp;gt; {ok,&amp;lt;0.49.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt; (bad@prestine)4&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Now close the frame and you should see:
&lt;br&gt;&amp;gt;&amp;gt; =ERROR REPORT==== 14-Oct-2009::13:17:08 ===
&lt;br&gt;&amp;gt;&amp;gt; ** Generic server &amp;lt;0.39.0&amp;gt; terminating
&lt;br&gt;&amp;gt;&amp;gt; ** Last message in was {'_wxe_destroy_',&amp;lt;3.42.0&amp;gt;}
&lt;br&gt;&amp;gt;&amp;gt; ** When Server state == {state,#Port&amp;lt;0.2605&amp;gt;,#Port&amp;lt;0.2602&amp;gt;,
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;  {1,{&amp;lt;0.32.0&amp;gt;,{user,[],[],undefined},nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;                              [&amp;lt;0.57.0&amp;gt;],
&lt;br&gt;&amp;gt;&amp;gt;                              {1,{#Fun&amp;lt;test.close.2&amp;gt;,1,nil,nil}},
&lt;br&gt;&amp;gt;&amp;gt;                              2}
&lt;br&gt;&amp;gt;&amp;gt; ** Reason for termination ==
&lt;br&gt;&amp;gt;&amp;gt; ** {badarg,[{erlang,is_process_alive,[&amp;lt;3.42.0&amp;gt;]},
&lt;br&gt;&amp;gt;&amp;gt;           {wxe_server,handle_info,2},
&lt;br&gt;&amp;gt;&amp;gt;           {gen_server,handle_msg,5},
&lt;br&gt;&amp;gt;&amp;gt;           {proc_lib,init_p_do_apply,3}]}
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; The pid which comes from the port is not recognized as a local pid and
&lt;br&gt;&amp;gt;&amp;gt; thus erlang:is_process_alive/1 will exit with badarg. My question is: Is
&lt;br&gt;&amp;gt;&amp;gt; this a &amp;quot;feature&amp;quot; or a bug? I think this is a bug but I'm not sure what is
&lt;br&gt;&amp;gt;&amp;gt; expected from the wx library point of view. IMHO it shouldn't crash and just
&lt;br&gt;&amp;gt;&amp;gt; ignore it in this case because the wxe_server shouldn't be allowed to crash.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Anyway I put in a patch as well just in case this is something that should
&lt;br&gt;&amp;gt;&amp;gt; be fixed. The patch can be applied to both wx 0.98.1 and 0.98.3.
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; Cheers,
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; ------------------------------------------------------------------------
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;/div&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wxe_server-bug--%28and-patch%29-tp25890987p25891504.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25891022</id>
	<title>Re: wxe_server bug? (and patch)</title>
	<published>2009-10-14T06:25:21Z</published>
	<updated>2009-10-14T06:25:21Z</updated>
	<author>
		<name>Mazen Harake-2</name>
	</author>
	<content type="html">A quick note:
&lt;br&gt;I just realized that this example doesn't work unless you have applied 
&lt;br&gt;my previous patch for wx_object.erl. Either apply that or change the 
&lt;br&gt;code to call the wx_object with the form (somehow) :)
&lt;br&gt;&lt;br&gt;/Mazen
&lt;br&gt;&lt;br&gt;Mazen Harake wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Hi,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; There is a situation in the wx library that causes the wxe_server to 
&lt;br&gt;&amp;gt; crash when it receives a message with a pid which is considered by 
&lt;br&gt;&amp;gt; distributed Erlang to come from another node when in fact it isn't. 
&lt;br&gt;&amp;gt; This happens when net_kernel is started explicitly (I.e. Erlang going 
&lt;br&gt;&amp;gt; into distribution mode) and an wx_object (which was created before 
&lt;br&gt;&amp;gt; net_kernel was started) is destroyed.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Here is a simple example:
&lt;br&gt;&amp;gt; Create this module:
&lt;br&gt;&amp;gt; -module(test).
&lt;br&gt;&amp;gt; -compile(export_all).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; start() -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;wx:new(),
&lt;br&gt;&amp;gt; &amp;nbsp;wx_object:start_link({local, ?MODULE}, ?MODULE, wx:get_env(), []).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; close(_, _) -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;wx_object:call(?MODULE, stop).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; init(Wx) -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;wx:set_env(Wx),
&lt;br&gt;&amp;gt; &amp;nbsp;Mf = wxFrame:new(wx:null(),1,&amp;quot;&amp;quot;,[{size,{300,300}}]),
&lt;br&gt;&amp;gt; &amp;nbsp;wxFrame:show(Mf),
&lt;br&gt;&amp;gt; &amp;nbsp;wxFrame:connect(Mf, close_window, [{callback, fun ?MODULE:close/2}]),
&lt;br&gt;&amp;gt; &amp;nbsp;{Mf, Mf}.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; handle_call(stop, _From, Mf) -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;wxFrame:destroy(Mf),
&lt;br&gt;&amp;gt; &amp;nbsp;{stop, normal, ok, Mf}.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; terminate(normal, _) -&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;ok.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Then run this in the shell:
&lt;br&gt;&amp;gt; Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Eshell V5.7.1 &amp;nbsp;(abort with ^G)
&lt;br&gt;&amp;gt; 1&amp;gt; c(test).
&lt;br&gt;&amp;gt; {ok,test}
&lt;br&gt;&amp;gt; 2&amp;gt; test:start().
&lt;br&gt;&amp;gt; {wx_ref,35,wxFrame,&amp;lt;0.42.0&amp;gt;}
&lt;br&gt;&amp;gt; 3&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; This should give you a small frame, don't close it yet,
&lt;br&gt;&amp;gt; Now do this:
&lt;br&gt;&amp;gt; 3&amp;gt; net_kernel:start([bad,shortnames]).
&lt;br&gt;&amp;gt; {ok,&amp;lt;0.49.0&amp;gt;}
&lt;br&gt;&amp;gt; (bad@prestine)4&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Now close the frame and you should see:
&lt;br&gt;&amp;gt; =ERROR REPORT==== 14-Oct-2009::13:17:08 ===
&lt;br&gt;&amp;gt; ** Generic server &amp;lt;0.39.0&amp;gt; terminating
&lt;br&gt;&amp;gt; ** Last message in was {'_wxe_destroy_',&amp;lt;3.42.0&amp;gt;}
&lt;br&gt;&amp;gt; ** When Server state == {state,#Port&amp;lt;0.2605&amp;gt;,#Port&amp;lt;0.2602&amp;gt;,
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 
&lt;br&gt;&amp;gt; {1,{&amp;lt;0.32.0&amp;gt;,{user,[],[],undefined},nil,nil}},
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&amp;lt;0.57.0&amp;gt;],
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {1,{#Fun&amp;lt;test.close.2&amp;gt;,1,nil,nil}},
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2}
&lt;br&gt;&amp;gt; ** Reason for termination ==
&lt;br&gt;&amp;gt; ** {badarg,[{erlang,is_process_alive,[&amp;lt;3.42.0&amp;gt;]},
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{wxe_server,handle_info,2},
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{gen_server,handle_msg,5},
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{proc_lib,init_p_do_apply,3}]}
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; The pid which comes from the port is not recognized as a local pid and 
&lt;br&gt;&amp;gt; thus erlang:is_process_alive/1 will exit with badarg. My question is: 
&lt;br&gt;&amp;gt; Is this a &amp;quot;feature&amp;quot; or a bug? I think this is a bug but I'm not sure 
&lt;br&gt;&amp;gt; what is expected from the wx library point of view. IMHO it shouldn't 
&lt;br&gt;&amp;gt; crash and just ignore it in this case because the wxe_server shouldn't 
&lt;br&gt;&amp;gt; be allowed to crash.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Anyway I put in a patch as well just in case this is something that 
&lt;br&gt;&amp;gt; should be fixed. The patch can be applied to both wx 0.98.1 and 0.98.3.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Cheers,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; ------------------------------------------------------------------------
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;/div&gt;&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wxe_server-bug--%28and-patch%29-tp25890987p25891022.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25890987</id>
	<title>wxe_server bug? (and patch)</title>
	<published>2009-10-14T06:22:42Z</published>
	<updated>2009-10-14T06:22:42Z</updated>
	<author>
		<name>Mazen Harake-2</name>
	</author>
	<content type="html">Hi,
&lt;br&gt;&lt;br&gt;There is a situation in the wx library that causes the wxe_server to 
&lt;br&gt;crash when it receives a message with a pid which is considered by 
&lt;br&gt;distributed Erlang to come from another node when in fact it isn't. This 
&lt;br&gt;happens when net_kernel is started explicitly (I.e. Erlang going into 
&lt;br&gt;distribution mode) and an wx_object (which was created before net_kernel 
&lt;br&gt;was started) is destroyed.
&lt;br&gt;&lt;br&gt;Here is a simple example:
&lt;br&gt;Create this module:
&lt;br&gt;-module(test).
&lt;br&gt;-compile(export_all).
&lt;br&gt;&lt;br&gt;start() -&amp;gt;
&lt;br&gt;&amp;nbsp; wx:new(),
&lt;br&gt;&amp;nbsp; wx_object:start_link({local, ?MODULE}, ?MODULE, wx:get_env(), []).
&lt;br&gt;&lt;br&gt;close(_, _) -&amp;gt;
&lt;br&gt;&amp;nbsp; wx_object:call(?MODULE, stop).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;init(Wx) -&amp;gt;
&lt;br&gt;&amp;nbsp; wx:set_env(Wx),
&lt;br&gt;&amp;nbsp; Mf = wxFrame:new(wx:null(),1,&amp;quot;&amp;quot;,[{size,{300,300}}]),
&lt;br&gt;&amp;nbsp; wxFrame:show(Mf),
&lt;br&gt;&amp;nbsp; wxFrame:connect(Mf, close_window, [{callback, fun ?MODULE:close/2}]),
&lt;br&gt;&amp;nbsp; {Mf, Mf}.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;handle_call(stop, _From, Mf) -&amp;gt;
&lt;br&gt;&amp;nbsp; wxFrame:destroy(Mf),
&lt;br&gt;&amp;nbsp; {stop, normal, ok, Mf}.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;terminate(normal, _) -&amp;gt;
&lt;br&gt;&amp;nbsp; ok.
&lt;br&gt;&lt;br&gt;Then run this in the shell:
&lt;br&gt;Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]
&lt;br&gt;&lt;br&gt;Eshell V5.7.1 &amp;nbsp;(abort with ^G)
&lt;br&gt;1&amp;gt; c(test).
&lt;br&gt;{ok,test}
&lt;br&gt;2&amp;gt; test:start().
&lt;br&gt;{wx_ref,35,wxFrame,&amp;lt;0.42.0&amp;gt;}
&lt;br&gt;3&amp;gt;
&lt;br&gt;&lt;br&gt;This should give you a small frame, don't close it yet,
&lt;br&gt;Now do this:
&lt;br&gt;3&amp;gt; net_kernel:start([bad,shortnames]).
&lt;br&gt;{ok,&amp;lt;0.49.0&amp;gt;}
&lt;br&gt;(bad@prestine)4&amp;gt;
&lt;br&gt;&lt;br&gt;Now close the frame and you should see:
&lt;br&gt;=ERROR REPORT==== 14-Oct-2009::13:17:08 ===
&lt;br&gt;** Generic server &amp;lt;0.39.0&amp;gt; terminating
&lt;br&gt;** Last message in was {'_wxe_destroy_',&amp;lt;3.42.0&amp;gt;}
&lt;br&gt;** When Server state == {state,#Port&amp;lt;0.2605&amp;gt;,#Port&amp;lt;0.2602&amp;gt;,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&lt;br&gt;{1,{&amp;lt;0.32.0&amp;gt;,{user,[],[],undefined},nil,nil}},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[&amp;lt;0.57.0&amp;gt;],
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{1,{#Fun&amp;lt;test.close.2&amp;gt;,1,nil,nil}},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2}
&lt;br&gt;** Reason for termination ==
&lt;br&gt;** {badarg,[{erlang,is_process_alive,[&amp;lt;3.42.0&amp;gt;]},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {wxe_server,handle_info,2},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {gen_server,handle_msg,5},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {proc_lib,init_p_do_apply,3}]}
&lt;br&gt;&lt;br&gt;&lt;br&gt;The pid which comes from the port is not recognized as a local pid and 
&lt;br&gt;thus erlang:is_process_alive/1 will exit with badarg. My question is: Is 
&lt;br&gt;this a &amp;quot;feature&amp;quot; or a bug? I think this is a bug but I'm not sure what 
&lt;br&gt;is expected from the wx library point of view. IMHO it shouldn't crash 
&lt;br&gt;and just ignore it in this case because the wxe_server shouldn't be 
&lt;br&gt;allowed to crash.
&lt;br&gt;&lt;br&gt;Anyway I put in a patch as well just in case this is something that 
&lt;br&gt;should be fixed. The patch can be applied to both wx 0.98.1 and 0.98.3.
&lt;br&gt;&lt;br&gt;Cheers,
&lt;br&gt;&lt;br&gt;/Mazen
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;--- wxe_server.original.erl	2009-09-24 11:00:48.000000000 +0200
&lt;br&gt;+++ wxe_server.erl	2009-10-14 15:06:41.141000000 +0200
&lt;br&gt;@@ -177,12 +177,11 @@
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{noreply, State}
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;handle_info(Msg = {'_wxe_destroy_', Pid}, State) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case erlang:is_process_alive(Pid) of
&lt;br&gt;-	true -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;Pid ! Msg,
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;-	false -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;ok
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;try
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;true = erlang:is_process_alive(Pid),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;Pid ! Msg
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;catch
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;error:_ -&amp;gt; ok
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{noreply, State};
&lt;br&gt;&amp;nbsp;handle_info(_Info, State) -&amp;gt;
&lt;br&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wxe_server-bug--%28and-patch%29-tp25890987p25890987.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25886967</id>
	<title>Re: [erlang-questions] blowfish ECB implementation in erlang?</title>
	<published>2009-10-14T01:05:46Z</published>
	<updated>2009-10-14T01:05:46Z</updated>
	<author>
		<name>puzza007</name>
	</author>
	<content type="html">On Sun, Sep 27, 2009 at 11:35 PM, Paul Oliver &lt;span dir=&quot;ltr&quot;&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25886967&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;puzza007@...&lt;/a&gt;&amp;gt;&lt;/span&gt; wrote:&lt;br&gt;&lt;div class=&quot;gmail_quote&quot;&gt;&lt;blockquote class=&quot;gmail_quote&quot; style=&quot;border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;&quot;&gt;

&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class=&quot;h5&quot;&gt;&lt;br&gt;&lt;br&gt;&lt;div class=&quot;gmail_quote&quot;&gt;On Fri, Sep 25, 2009 at 1:19 PM, Paul Oliver &lt;span dir=&quot;ltr&quot;&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25886967&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;puzza007@...&lt;/a&gt;&amp;gt;&lt;/span&gt; wrote:&lt;br&gt;

&lt;blockquote class=&quot;gmail_quote&quot; style=&quot;border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;&quot;&gt;
&lt;div class=&quot;gmail_quote&quot;&gt;&lt;div&gt;On Wed, Sep 23, 2009 at 8:33 PM, Larry Ogrodnek &lt;span dir=&quot;ltr&quot;&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25886967&amp;i=2&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;larry@...&lt;/a&gt;&amp;gt;&lt;/span&gt; wrote:&lt;br&gt;&lt;blockquote class=&quot;gmail_quote&quot; style=&quot;border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;&quot;&gt;




Hi, I&amp;#39;m wondering if anyone has put together an implementation of blowfish ECB?&lt;br&gt;
&lt;br&gt;
thanks.&lt;br&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;Hi Larry,&lt;br&gt;&lt;br&gt;Check the following page for the patch that added cfb64.&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://www.nabble.com/Patch-to-add-Blowfish-cfb64-to-crypto-app-td24232164.html&quot; target=&quot;_blank&quot;&gt;http://www.nabble.com/Patch-to-add-Blowfish-cfb64-to-crypto-app-td24232164.html&lt;/a&gt;&lt;br&gt;




&lt;br&gt;You should almost be able to copy this verbatim to add ecb.&lt;br&gt;&lt;br&gt;Cheers,&lt;br&gt;Paul.&lt;br&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/blockquote&gt;&lt;/div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;Hi Larry,&lt;br&gt;&lt;br&gt;The attached patch should do ECB for you.  It works for me on the test data I obtained from &lt;a href=&quot;http://www.schneier.com/code/vectors.txt&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://www.schneier.com/code/vectors.txt&lt;/a&gt;.&lt;br&gt;


&lt;br&gt;puzza@imac:~/Downloads/otp_src_R13B02-1$ /tmp/bin/erl&lt;br&gt;Erlang R13B02 (erts-5.7.3) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]&lt;br&gt;&lt;br&gt;Eshell V5.7.3  (abort with ^G)&lt;br&gt;1&amp;gt; %% FEDCBA9876543210 == Key = &amp;lt;&amp;lt;254,220,186,152,118,84,50,16&amp;gt;&amp;gt;&lt;br&gt;


1&amp;gt; %% 0123456789ABCDEF == Clear = &amp;lt;&amp;lt;1,35,69,103,137,171,205,239&amp;gt;&amp;gt;&lt;br&gt;1&amp;gt; %% 0ACEAB0FC6A0A28D == Enc = &amp;lt;&amp;lt;10,206,171,15,198,160,162,141&amp;gt;&amp;gt;&lt;br&gt;1&amp;gt; &lt;br&gt;1&amp;gt; crypto:start().&lt;br&gt;ok&lt;br&gt;2&amp;gt; Key = &amp;lt;&amp;lt;254,220,186,152,118,84,50,16&amp;gt;&amp;gt;.&lt;br&gt;


&amp;lt;&amp;lt;254,220,186,152,118,84,50,16&amp;gt;&amp;gt;&lt;br&gt;3&amp;gt; Clear = &amp;lt;&amp;lt;1,35,69,103,137,171,205,239&amp;gt;&amp;gt;.&lt;br&gt;&amp;lt;&amp;lt;1,35,69,103,137,171,205,239&amp;gt;&amp;gt;&lt;br&gt;4&amp;gt; Enc = &amp;lt;&amp;lt;10,206,171,15,198,160,162,141&amp;gt;&amp;gt;.&lt;br&gt;&amp;lt;&amp;lt;10,206,171,15,198,160,162,141&amp;gt;&amp;gt;&lt;br&gt;


5&amp;gt; Enc == crypto:blowfish_ecb_encrypt(Key, Clear).&lt;br&gt;true&lt;br&gt;6&amp;gt;  Clear == crypto:blowfish_ecb_decrypt(Key, Enc).&lt;br&gt;true&lt;br&gt;7&amp;gt;&lt;br&gt;&lt;br&gt;I&amp;#39;m off on holiday tomorrow so if it doesn&amp;#39;t work as it should I&amp;#39;ll take another look in a couple of weeks.  ;}  If it works OK please reply and perhaps it can be picked up in a future OTP release.&lt;br&gt;


&lt;br&gt;Cheers,&lt;br&gt;&lt;font color=&quot;#888888&quot;&gt;Paul.&lt;br&gt;
&lt;/font&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;br&gt;Hi,&lt;br&gt;
&lt;br&gt;
I&amp;#39;ve rounded out the patch to include the rest of the blowfish functions from openssl and included a primitive test program.&lt;br&gt;
&lt;br&gt;
Cheers,&lt;br&gt;
Paul.&lt;br&gt;
&lt;br /&gt;&lt;tt&gt;[blowfish_ecb_cbc_ofb.patch]&lt;/tt&gt;&lt;br /&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;tt&gt;diff --git a/lib/crypto/c_src/crypto_drv.c b/lib/crypto/c_src/crypto_drv.c
&lt;br&gt;index a5b301f..9d99591 100644
&lt;br&gt;--- a/lib/crypto/c_src/crypto_drv.c
&lt;br&gt;+++ b/lib/crypto/c_src/crypto_drv.c
&lt;br&gt;@@ -212,6 +212,11 @@ static ErlDrvEntry crypto_driver_entry = {
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;#define DRV_BF_CFB64_ENCRYPT &amp;nbsp; &amp;nbsp; 59
&lt;br&gt;&amp;nbsp;#define DRV_BF_CFB64_DECRYPT &amp;nbsp; &amp;nbsp; 60
&lt;br&gt;+#define DRV_BF_ECB_ENCRYPT &amp;nbsp; &amp;nbsp; &amp;nbsp; 61
&lt;br&gt;+#define DRV_BF_ECB_DECRYPT &amp;nbsp; &amp;nbsp; &amp;nbsp; 62
&lt;br&gt;+#define DRV_BF_OFB64_ENCRYPT &amp;nbsp; &amp;nbsp; 63
&lt;br&gt;+#define DRV_BF_CBC_ENCRYPT &amp;nbsp; &amp;nbsp; &amp;nbsp; 64
&lt;br&gt;+#define DRV_BF_CBC_DECRYPT &amp;nbsp; &amp;nbsp; &amp;nbsp; 65
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;/* #define DRV_CBC_IDEA_ENCRYPT &amp;nbsp; &amp;nbsp;34 */
&lt;br&gt;&amp;nbsp;/* #define DRV_CBC_IDEA_DECRYPT &amp;nbsp; &amp;nbsp;35 */
&lt;br&gt;@@ -507,17 +512,63 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (command == DRV_CBC_DES_ENCRYPT));
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return dlen;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case DRV_BF_ECB_ENCRYPT:
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case DRV_BF_ECB_DECRYPT:
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{
&lt;br&gt;+	/* buf = klen[4] key data */
&lt;br&gt;+	int bf_direction;
&lt;br&gt;+	const unsigned char *bf_dbuf; /* blowfish input data */
&lt;br&gt;+	BF_KEY bf_key; /* blowfish key 8 */
&lt;br&gt;+
&lt;br&gt;+	klen = get_int32(buf);
&lt;br&gt;+	key = buf + 4;
&lt;br&gt;+	bf_dbuf = key + klen;
&lt;br&gt;+	dlen = len - 4 - klen;
&lt;br&gt;+	if (dlen &amp;lt; 0) return -1;
&lt;br&gt;+	BF_set_key(&amp;bf_key, klen, key);
&lt;br&gt;+	bin = return_binary(rbuf,rlen,dlen);
&lt;br&gt;+	if (bin==NULL) return -1;
&lt;br&gt;+	bf_direction = command == DRV_BF_ECB_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT;
&lt;br&gt;+	BF_ecb_encrypt(bf_dbuf, bin, &amp;bf_key, bf_direction);
&lt;br&gt;+	return dlen;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case DRV_BF_CBC_ENCRYPT:
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case DRV_BF_CBC_DECRYPT:
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{
&lt;br&gt;+	/* buf = klen[4] key ivec[8] data */
&lt;br&gt;+	char* ivec;
&lt;br&gt;+	unsigned char bf_tkey[8]; /* blowfish ivec */
&lt;br&gt;+	int bf_direction;
&lt;br&gt;+	const unsigned char *bf_dbuf; /* blowfish input data */
&lt;br&gt;+	BF_KEY bf_key; /* blowfish key 8 */
&lt;br&gt;+
&lt;br&gt;+	klen = get_int32(buf);
&lt;br&gt;+	key = buf + 4;
&lt;br&gt;+	ivec = key + klen;
&lt;br&gt;+	bf_dbuf = ivec + 8;
&lt;br&gt;+	dlen = len - 4 - klen - 8;
&lt;br&gt;+	if (dlen &amp;lt; 0) return -1;
&lt;br&gt;+	BF_set_key(&amp;bf_key, klen, key);
&lt;br&gt;+	memcpy(bf_tkey, ivec, 8);
&lt;br&gt;+	bin = return_binary(rbuf,rlen,dlen);
&lt;br&gt;+	if (bin==NULL) return -1;
&lt;br&gt;+	bf_direction = command == DRV_BF_CBC_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT;
&lt;br&gt;+	BF_cbc_encrypt(bf_dbuf, bin, dlen, &amp;bf_key, bf_tkey, bf_direction);
&lt;br&gt;+	return dlen;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case DRV_BF_CFB64_ENCRYPT:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case DRV_BF_CFB64_DECRYPT:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&lt;br&gt;&amp;nbsp;	/* buf = klen[4] key ivec[8] data */
&lt;br&gt;&amp;nbsp;	char* ivec;
&lt;br&gt;-	unsigned char bf_tkey[8]; /* blowfish ivec */ &amp;nbsp; &amp;nbsp;
&lt;br&gt;-	int bf_n; /* blowfish ivec pos */ &amp;nbsp; &amp;nbsp;
&lt;br&gt;+	unsigned char bf_tkey[8]; /* blowfish ivec */
&lt;br&gt;+	int bf_n; /* blowfish ivec pos */
&lt;br&gt;&amp;nbsp;	int bf_direction;
&lt;br&gt;-	const unsigned char *bf_dbuf; /* blowfish input data */ &amp;nbsp; 
&lt;br&gt;+	const unsigned char *bf_dbuf; /* blowfish input data */
&lt;br&gt;&amp;nbsp;	BF_KEY bf_key; /* blowfish key 8 */
&lt;br&gt;-	
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;	klen = get_int32(buf);
&lt;br&gt;&amp;nbsp;	key = buf + 4;
&lt;br&gt;&amp;nbsp;	ivec = key + klen;
&lt;br&gt;@@ -534,6 +585,30 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf,
&lt;br&gt;&amp;nbsp;	return dlen;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case DRV_BF_OFB64_ENCRYPT:
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{
&lt;br&gt;+	/* buf = klen[4] key ivec[8] data */
&lt;br&gt;+	char* ivec;
&lt;br&gt;+	unsigned char bf_tkey[8]; /* blowfish ivec */
&lt;br&gt;+	int bf_n; /* blowfish ivec pos */
&lt;br&gt;+	const unsigned char *bf_dbuf; /* blowfish input data */
&lt;br&gt;+	BF_KEY bf_key; /* blowfish key 8 */
&lt;br&gt;+
&lt;br&gt;+	klen = get_int32(buf);
&lt;br&gt;+	key = buf + 4;
&lt;br&gt;+	ivec = key + klen;
&lt;br&gt;+	bf_dbuf = ivec + 8;
&lt;br&gt;+	dlen = len - 4 - klen - 8;
&lt;br&gt;+	if (dlen &amp;lt; 0) return -1;
&lt;br&gt;+	BF_set_key(&amp;bf_key, klen, key);
&lt;br&gt;+	memcpy(bf_tkey, ivec, 8);
&lt;br&gt;+	bin = return_binary(rbuf,rlen,dlen);
&lt;br&gt;+	if (bin==NULL) return -1;
&lt;br&gt;+	bf_n = 0;
&lt;br&gt;+	BF_ofb64_encrypt(bf_dbuf, bin, dlen, &amp;bf_key, bf_tkey, &amp;bf_n);
&lt;br&gt;+	return dlen;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;/* &amp;nbsp; &amp;nbsp; case DRV_CBC_IDEA_ENCRYPT: */
&lt;br&gt;&amp;nbsp;/* &amp;nbsp; &amp;nbsp; case DRV_CBC_IDEA_DECRYPT: */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* buf = key[16] ivec[8] data */
&lt;br&gt;diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
&lt;br&gt;index 7d96017..38dacc0 100644
&lt;br&gt;--- a/lib/crypto/doc/src/crypto.xml
&lt;br&gt;+++ b/lib/crypto/doc/src/crypto.xml
&lt;br&gt;@@ -337,6 +337,53 @@ Mpint() = &amp;lt;![CDATA[&amp;lt;&amp;lt;ByteLen:32/integer-big, Bytes:ByteLen/binary&amp;gt;&amp;gt;]]&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;c&amp;gt;Key3&amp;lt;/c&amp;gt;, and &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt; must be 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/func&amp;gt;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;func&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_ecb_encrypt(Key, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Encrypt the first 64 bits of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in ECB mode&amp;lt;/fsummary&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;Key = Text = iolist() | binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;IVec = Cipher = binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;p&amp;gt;Encrypts the first 64 bits of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in ECB mode. &amp;lt;c&amp;gt;Key&amp;lt;/c&amp;gt; is the Blowfish key. The length of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; must be at least 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_ecb_decrypt(Key, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Decrypt the first 64 bits of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in ECB mode&amp;lt;/fsummary&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;Key = Text = iolist() | binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;IVec = Cipher = binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;p&amp;gt;Decrypts the first 64 bits of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in ECB mode. &amp;lt;c&amp;gt;Key&amp;lt;/c&amp;gt; is the Blowfish key. The length of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; must be at least 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;/func&amp;gt;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;func&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_cbc_encrypt(Key, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Encrypt &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in CBC mode&amp;lt;/fsummary&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;Key = Text = iolist() | binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;IVec = Cipher = binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;p&amp;gt;Encrypts &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in CBC mode. &amp;lt;c&amp;gt;Key&amp;lt;/c&amp;gt; is the Blowfish key, and &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt; is an
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;arbitrary initializing vector. The length of &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;must be 64 bits (8 bytes). The length of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; must be a multiple of 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_cbc_decrypt(Key, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Decrypt &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in CBC mode&amp;lt;/fsummary&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;Key = Text = iolist() | binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;IVec = Cipher = binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;p&amp;gt;Decrypts &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in CBC mode. &amp;lt;c&amp;gt;Key&amp;lt;/c&amp;gt; is the Blowfish key, and &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt; is an
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;arbitrary initializing vector. The length of &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;must be 64 bits (8 bytes). The length of &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; must be a multiple 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;/func&amp;gt;
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;func&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_cfb64_encrypt(Key, IVec, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Encrypt &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt;using Blowfish in CFB mode with 64
&lt;br&gt;@@ -367,6 +414,23 @@ Mpint() = &amp;lt;![CDATA[&amp;lt;&amp;lt;ByteLen:32/integer-big, Bytes:ByteLen/binary&amp;gt;&amp;gt;]]&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;must be 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/func&amp;gt;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;func&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;blowfish_ofb64_encrypt(Key, IVec, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;fsummary&amp;gt;Encrypt &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt;using Blowfish in OFB mode with 64
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;bit feedback&amp;lt;/fsummary&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;Key = Text = iolist() | binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;v&amp;gt;IVec = Cipher = binary()&amp;lt;/v&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/type&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;p&amp;gt;Encrypts &amp;lt;c&amp;gt;Text&amp;lt;/c&amp;gt; using Blowfish in OFB mode with 64 bit
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;feedback. &amp;lt;c&amp;gt;Key&amp;lt;/c&amp;gt; is the Blowfish key, and &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt; is an
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;arbitrary initializing vector. The length of &amp;lt;c&amp;gt;IVec&amp;lt;/c&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;must be 64 bits (8 bytes).&amp;lt;/p&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/desc&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;&amp;lt;/func&amp;gt;
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;func&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;aes_cfb_128_encrypt(Key, IVec, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;name&amp;gt;aes_cbc_128_encrypt(Key, IVec, Text) -&amp;gt; Cipher&amp;lt;/name&amp;gt;
&lt;br&gt;diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
&lt;br&gt;index 5189677..fa33bad 100644
&lt;br&gt;--- a/lib/crypto/src/crypto.erl
&lt;br&gt;+++ b/lib/crypto/src/crypto.erl
&lt;br&gt;@@ -30,7 +30,10 @@
&lt;br&gt;&amp;nbsp;-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]).
&lt;br&gt;&amp;nbsp;-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
&lt;br&gt;&amp;nbsp;-export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]).
&lt;br&gt;--export([blowfish_cfb64_encrypt/3,blowfish_cfb64_decrypt/3]).
&lt;br&gt;+-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]).
&lt;br&gt;+-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]).
&lt;br&gt;+-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]).
&lt;br&gt;+-export([blowfish_ofb64_encrypt/3]).
&lt;br&gt;&amp;nbsp;-export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]).
&lt;br&gt;&amp;nbsp;-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
&lt;br&gt;&amp;nbsp;-export([exor/2]).
&lt;br&gt;@@ -115,6 +118,11 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;-define(BF_CFB64_ENCRYPT, 59).
&lt;br&gt;&amp;nbsp;-define(BF_CFB64_DECRYPT, 60).
&lt;br&gt;+-define(BF_ECB_ENCRYPT, &amp;nbsp; 61).
&lt;br&gt;+-define(BF_ECB_DECRYPT, &amp;nbsp; 62).
&lt;br&gt;+-define(BF_OFB64_ENCRYPT, 63).
&lt;br&gt;+-define(BF_CBC_ENCRYPT, &amp;nbsp; 64).
&lt;br&gt;+-define(BF_CBC_DECRYPT, &amp;nbsp; 65).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% -define(IDEA_CBC_ENCRYPT, 34).
&lt;br&gt;&amp;nbsp;%% -define(IDEA_CBC_DECRYPT, 35).
&lt;br&gt;@@ -303,12 +311,27 @@ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) -&amp;gt;
&lt;br&gt;&amp;nbsp;%%
&lt;br&gt;&amp;nbsp;%% Blowfish
&lt;br&gt;&amp;nbsp;%%
&lt;br&gt;+blowfish_ecb_encrypt(Key, Data) when byte_size(Data) &amp;gt;= 8 -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;control_bin(?BF_ECB_ENCRYPT, Key, list_to_binary([Data])).
&lt;br&gt;+
&lt;br&gt;+blowfish_ecb_decrypt(Key, Data) when byte_size(Data) &amp;gt;= 8 -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;control_bin(?BF_ECB_DECRYPT, Key, list_to_binary([Data])).
&lt;br&gt;+
&lt;br&gt;+blowfish_cbc_encrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;control_bin(?BF_CBC_ENCRYPT, Key, list_to_binary([IVec, Data])).
&lt;br&gt;+
&lt;br&gt;+blowfish_cbc_decrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;control_bin(?BF_CBC_DECRYPT, Key, list_to_binary([IVec, Data])).
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;blowfish_cfb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;control_bin(?BF_CFB64_ENCRYPT, Key, list_to_binary([IVec, Data])).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;blowfish_cfb64_decrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;control_bin(?BF_CFB64_DECRYPT, Key, list_to_binary([IVec, Data])).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+blowfish_ofb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;control_bin(?BF_OFB64_ENCRYPT, Key, list_to_binary([IVec, Data])).
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;%%
&lt;br&gt;&amp;nbsp;%% AES in cipher feedback mode (CFB)
&lt;br&gt;&amp;nbsp;%%
&lt;br&gt;&lt;/tt&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;br /&gt;&lt;tt&gt;[bf_test.erl]&lt;/tt&gt;&lt;br /&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;tt&gt;-module(bf_test).
&lt;br&gt;&lt;br&gt;-include_lib(&amp;quot;eunit/include/eunit.hrl&amp;quot;).
&lt;br&gt;&lt;br&gt;-define(KEY, to_bin(&amp;quot;0123456789ABCDEFF0E1D2C3B4A59687&amp;quot;)).
&lt;br&gt;-define(IVEC, to_bin(&amp;quot;FEDCBA9876543210&amp;quot;)).
&lt;br&gt;%% &amp;quot;7654321 Now is the time for &amp;quot; (includes trailing '\0')
&lt;br&gt;-define(DATA, to_bin(&amp;quot;37363534333231204E6F77206973207468652074696D6520666F722000&amp;quot;)).
&lt;br&gt;-define(DATA_PADDED, to_bin(&amp;quot;37363534333231204E6F77206973207468652074696D6520666F722000000000&amp;quot;)).
&lt;br&gt;&lt;br&gt;&lt;br&gt;ecb_test(KeyBytes, ClearBytes, CipherBytes) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; crypto:start(),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {Key, Clear, Cipher} =
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {to_bin(KeyBytes), to_bin(ClearBytes), to_bin(CipherBytes)},
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; crypto:blowfish_ecb_encrypt(Key, Clear) =:= Cipher.
&lt;br&gt;&lt;br&gt;ecb_1_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0000000000000000&amp;quot;, &amp;quot;0000000000000000&amp;quot;, &amp;quot;4EF997456198DD78&amp;quot;)).
&lt;br&gt;ecb_2_test() -&amp;gt; ?assert(ecb_test(&amp;quot;FFFFFFFFFFFFFFFF&amp;quot;, &amp;quot;FFFFFFFFFFFFFFFF&amp;quot;, &amp;quot;51866FD5B85ECB8A&amp;quot;)).
&lt;br&gt;ecb_3_test() -&amp;gt; ?assert(ecb_test(&amp;quot;3000000000000000&amp;quot;, &amp;quot;1000000000000001&amp;quot;, &amp;quot;7D856F9A613063F2&amp;quot;)).
&lt;br&gt;ecb_4_test() -&amp;gt; ?assert(ecb_test(&amp;quot;1111111111111111&amp;quot;, &amp;quot;1111111111111111&amp;quot;, &amp;quot;2466DD878B963C9D&amp;quot;)).
&lt;br&gt;ecb_5_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;1111111111111111&amp;quot;, &amp;quot;61F9C3802281B096&amp;quot;)).
&lt;br&gt;ecb_6_test() -&amp;gt; ?assert(ecb_test(&amp;quot;1111111111111111&amp;quot;, &amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;7D0CC630AFDA1EC7&amp;quot;)).
&lt;br&gt;ecb_7_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0000000000000000&amp;quot;, &amp;quot;0000000000000000&amp;quot;, &amp;quot;4EF997456198DD78&amp;quot;)).
&lt;br&gt;ecb_8_test() -&amp;gt; ?assert(ecb_test(&amp;quot;FEDCBA9876543210&amp;quot;, &amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;0ACEAB0FC6A0A28D&amp;quot;)).
&lt;br&gt;ecb_9_test() -&amp;gt; ?assert(ecb_test(&amp;quot;7CA110454A1A6E57&amp;quot;, &amp;quot;01A1D6D039776742&amp;quot;, &amp;quot;59C68245EB05282B&amp;quot;)).
&lt;br&gt;ecb_10_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0131D9619DC1376E&amp;quot;, &amp;quot;5CD54CA83DEF57DA&amp;quot;, &amp;quot;B1B8CC0B250F09A0&amp;quot;)).
&lt;br&gt;ecb_11_test() -&amp;gt; ?assert(ecb_test(&amp;quot;07A1133E4A0B2686&amp;quot;, &amp;quot;0248D43806F67172&amp;quot;, &amp;quot;1730E5778BEA1DA4&amp;quot;)).
&lt;br&gt;ecb_12_test() -&amp;gt; ?assert(ecb_test(&amp;quot;3849674C2602319E&amp;quot;, &amp;quot;51454B582DDF440A&amp;quot;, &amp;quot;A25E7856CF2651EB&amp;quot;)).
&lt;br&gt;ecb_13_test() -&amp;gt; ?assert(ecb_test(&amp;quot;04B915BA43FEB5B6&amp;quot;, &amp;quot;42FD443059577FA2&amp;quot;, &amp;quot;353882B109CE8F1A&amp;quot;)).
&lt;br&gt;ecb_14_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0113B970FD34F2CE&amp;quot;, &amp;quot;059B5E0851CF143A&amp;quot;, &amp;quot;48F4D0884C379918&amp;quot;)).
&lt;br&gt;ecb_15_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0170F175468FB5E6&amp;quot;, &amp;quot;0756D8E0774761D2&amp;quot;, &amp;quot;432193B78951FC98&amp;quot;)).
&lt;br&gt;ecb_16_test() -&amp;gt; ?assert(ecb_test(&amp;quot;43297FAD38E373FE&amp;quot;, &amp;quot;762514B829BF486A&amp;quot;, &amp;quot;13F04154D69D1AE5&amp;quot;)).
&lt;br&gt;ecb_17_test() -&amp;gt; ?assert(ecb_test(&amp;quot;07A7137045DA2A16&amp;quot;, &amp;quot;3BDD119049372802&amp;quot;, &amp;quot;2EEDDA93FFD39C79&amp;quot;)).
&lt;br&gt;ecb_18_test() -&amp;gt; ?assert(ecb_test(&amp;quot;04689104C2FD3B2F&amp;quot;, &amp;quot;26955F6835AF609A&amp;quot;, &amp;quot;D887E0393C2DA6E3&amp;quot;)).
&lt;br&gt;ecb_19_test() -&amp;gt; ?assert(ecb_test(&amp;quot;37D06BB516CB7546&amp;quot;, &amp;quot;164D5E404F275232&amp;quot;, &amp;quot;5F99D04F5B163969&amp;quot;)).
&lt;br&gt;ecb_20_test() -&amp;gt; ?assert(ecb_test(&amp;quot;1F08260D1AC2465E&amp;quot;, &amp;quot;6B056E18759F5CCA&amp;quot;, &amp;quot;4A057A3B24D3977B&amp;quot;)).
&lt;br&gt;ecb_21_test() -&amp;gt; ?assert(ecb_test(&amp;quot;584023641ABA6176&amp;quot;, &amp;quot;004BD6EF09176062&amp;quot;, &amp;quot;452031C1E4FADA8E&amp;quot;)).
&lt;br&gt;ecb_22_test() -&amp;gt; ?assert(ecb_test(&amp;quot;025816164629B007&amp;quot;, &amp;quot;480D39006EE762F2&amp;quot;, &amp;quot;7555AE39F59B87BD&amp;quot;)).
&lt;br&gt;ecb_23_test() -&amp;gt; ?assert(ecb_test(&amp;quot;49793EBC79B3258F&amp;quot;, &amp;quot;437540C8698F3CFA&amp;quot;, &amp;quot;53C55F9CB49FC019&amp;quot;)).
&lt;br&gt;ecb_24_test() -&amp;gt; ?assert(ecb_test(&amp;quot;4FB05E1515AB73A7&amp;quot;, &amp;quot;072D43A077075292&amp;quot;, &amp;quot;7A8E7BFA937E89A3&amp;quot;)).
&lt;br&gt;ecb_25_test() -&amp;gt; ?assert(ecb_test(&amp;quot;49E95D6D4CA229BF&amp;quot;, &amp;quot;02FE55778117F12A&amp;quot;, &amp;quot;CF9C5D7A4986ADB5&amp;quot;)).
&lt;br&gt;ecb_26_test() -&amp;gt; ?assert(ecb_test(&amp;quot;018310DC409B26D6&amp;quot;, &amp;quot;1D9D5C5018F728C2&amp;quot;, &amp;quot;D1ABB290658BC778&amp;quot;)).
&lt;br&gt;ecb_27_test() -&amp;gt; ?assert(ecb_test(&amp;quot;1C587F1C13924FEF&amp;quot;, &amp;quot;305532286D6F295A&amp;quot;, &amp;quot;55CB3774D13EF201&amp;quot;)).
&lt;br&gt;ecb_28_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0101010101010101&amp;quot;, &amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;FA34EC4847B268B2&amp;quot;)).
&lt;br&gt;ecb_29_test() -&amp;gt; ?assert(ecb_test(&amp;quot;1F1F1F1F0E0E0E0E&amp;quot;, &amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;A790795108EA3CAE&amp;quot;)).
&lt;br&gt;ecb_30_test() -&amp;gt; ?assert(ecb_test(&amp;quot;E0FEE0FEF1FEF1FE&amp;quot;, &amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;C39E072D9FAC631D&amp;quot;)).
&lt;br&gt;ecb_31_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0000000000000000&amp;quot;, &amp;quot;FFFFFFFFFFFFFFFF&amp;quot;, &amp;quot;014933E0CDAFF6E4&amp;quot;)).
&lt;br&gt;ecb_32_test() -&amp;gt; ?assert(ecb_test(&amp;quot;FFFFFFFFFFFFFFFF&amp;quot;, &amp;quot;0000000000000000&amp;quot;, &amp;quot;F21E9A77B71C49BC&amp;quot;)).
&lt;br&gt;ecb_33_test() -&amp;gt; ?assert(ecb_test(&amp;quot;0123456789ABCDEF&amp;quot;, &amp;quot;0000000000000000&amp;quot;, &amp;quot;245946885754369A&amp;quot;)).
&lt;br&gt;ecb_34_test() -&amp;gt; ?assert(ecb_test(&amp;quot;FEDCBA9876543210&amp;quot;, &amp;quot;FFFFFFFFFFFFFFFF&amp;quot;, &amp;quot;6B5C5A9C5D9E0A5A&amp;quot;)).
&lt;br&gt;&lt;br&gt;%% Chaining mode tests
&lt;br&gt;cbc_test() -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; crypto:start(),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ?assert(crypto:blowfish_cbc_encrypt(?KEY, ?IVEC, ?DATA_PADDED) =:=
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to_bin(&amp;quot;6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC&amp;quot;)).
&lt;br&gt;&lt;br&gt;cfb64_test() -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; crypto:start(),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ?assert(crypto:blowfish_cfb64_encrypt(?KEY, ?IVEC, ?DATA) =:=
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to_bin(&amp;quot;E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3&amp;quot;)).
&lt;br&gt;&lt;br&gt;ofb64_test() -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; crypto:start(),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ?assert(crypto:blowfish_ofb64_encrypt(?KEY, ?IVEC, ?DATA) =:=
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to_bin(&amp;quot;E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA&amp;quot;)).
&lt;br&gt;&lt;br&gt;%% @spec to_bin(string()) -&amp;gt; binary()
&lt;br&gt;%% @doc Convert a hexadecimal string to a binary.
&lt;br&gt;to_bin(L) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; to_bin(L, []).
&lt;br&gt;&lt;br&gt;%% @spec dehex(char()) -&amp;gt; integer()
&lt;br&gt;%% @doc Convert a hex digit to its integer value.
&lt;br&gt;dehex(C) when C &amp;gt;= $0, C =&amp;lt; $9 -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; C - $0;
&lt;br&gt;dehex(C) when C &amp;gt;= $a, C =&amp;lt; $f -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; C - $a + 10;
&lt;br&gt;dehex(C) when C &amp;gt;= $A, C =&amp;lt; $F -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; C - $A + 10.
&lt;br&gt;&lt;br&gt;to_bin([], Acc) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; iolist_to_binary(lists:reverse(Acc));
&lt;br&gt;to_bin([C1, C2 | Rest], Acc) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; to_bin(Rest, [(dehex(C1) bsl 4) bor dehex(C2) | Acc]).
&lt;br&gt;&lt;/tt&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Re%3A--erlang-questions--blowfish-ECB-implementation-in-erlang--tp25638342p25886967.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25862782</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in  get_diagnos function</title>
	<published>2009-10-12T13:33:16Z</published>
	<updated>2009-10-12T13:33:16Z</updated>
	<author>
		<name>Juhani Ränkimies-2</name>
	</author>
	<content type="html">On 10/11/09, Andrew Thompson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25862782&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;andrew@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Ah, that does sound like a similar issue although I'm not sure my patch
&lt;br&gt;&amp;gt; will solve it. Does it happen consistantly or is it random? Are you
&lt;br&gt;&amp;gt; using parameterized queries?
&lt;br&gt;&lt;br&gt;I haven't worked with that part of the system in 5-6 months and i'm no
&lt;br&gt;longer sure if it was consistent or not. I'm on a trip and can't check
&lt;br&gt;it now. I'll try to find time to reproduce it on weekend.
&lt;br&gt;&lt;br&gt;Juhani
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25862782.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25846132</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in get_diagnos function</title>
	<published>2009-10-11T11:17:16Z</published>
	<updated>2009-10-11T11:17:16Z</updated>
	<author>
		<name>Andrew Thompson-15</name>
	</author>
	<content type="html">On Sun, Oct 11, 2009 at 10:40:10AM +0300, Juhani R?nkimies wrote:
&lt;br&gt;&amp;gt; On Sat, Oct 10, 2009 at 7:45 PM, Andrew Thompson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25846132&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;andrew@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;gt; Sometimes when an update/insert/delete is successfully executed in the
&lt;br&gt;&amp;gt; db, I get {error,&amp;quot;No SQL-driver information available.&amp;quot;}.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; My assumption (with no factual support) is that odbc app gets confused
&lt;br&gt;&amp;gt; if the db sends additional information (SQLSTATE?) about the execution
&lt;br&gt;&amp;gt; of the statement, like nulls ignored by aggregate functions or info
&lt;br&gt;&amp;gt; about type conversions that were made.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&lt;br&gt;Ah, that does sound like a similar issue although I'm not sure my patch
&lt;br&gt;will solve it. Does it happen consistantly or is it random? Are you
&lt;br&gt;using parameterized queries?
&lt;br&gt;&lt;br&gt;Andrew
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25846132.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25841309</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in  get_diagnos function</title>
	<published>2009-10-11T00:40:10Z</published>
	<updated>2009-10-11T00:40:10Z</updated>
	<author>
		<name>Juhani Ränkimies-2</name>
	</author>
	<content type="html">On Sat, Oct 10, 2009 at 7:45 PM, Andrew Thompson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25841309&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;andrew@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&lt;br&gt;&amp;gt;&amp;gt;
&lt;br&gt;&amp;gt; If it doesn't, I can try to resurrect my windows build setup and do some
&lt;br&gt;&amp;gt; investigating. What behaviour are you seeing?
&lt;br&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;Sometimes when an update/insert/delete is successfully executed in the
&lt;br&gt;db, I get {error,&amp;quot;No SQL-driver information available.&amp;quot;}.
&lt;br&gt;&lt;br&gt;My assumption (with no factual support) is that odbc app gets confused
&lt;br&gt;if the db sends additional information (SQLSTATE?) about the execution
&lt;br&gt;of the statement, like nulls ignored by aggregate functions or info
&lt;br&gt;about type conversions that were made.
&lt;br&gt;&lt;br&gt;-juhani
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25841309.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25836063</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in get_diagnos function</title>
	<published>2009-10-10T09:45:45Z</published>
	<updated>2009-10-10T09:45:45Z</updated>
	<author>
		<name>Andrew Thompson-15</name>
	</author>
	<content type="html">On Sat, Oct 10, 2009 at 10:30:48AM +0300, Juhani R?nkimies wrote:
&lt;br&gt;&amp;gt; I've had similar problems on windows with mssql2008. The behaviour
&lt;br&gt;&amp;gt; wasn't identical, but with luck your patch fixes it in my setup too.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; I'll definitely have a look. It'll take a while though, as setting up
&lt;br&gt;&amp;gt; a build env in windows is laborious and I've got my hands full
&lt;br&gt;&amp;gt; already.
&lt;br&gt;&amp;gt; 
&lt;br&gt;If it doesn't, I can try to resurrect my windows build setup and do some
&lt;br&gt;investigating. What behaviour are you seeing?
&lt;br&gt;&lt;br&gt;Andrew
&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25836063.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25831764</id>
	<title>Re: PATCH: ODBC application discarding sqlstate in  get_diagnos function</title>
	<published>2009-10-10T00:30:48Z</published>
	<updated>2009-10-10T00:30:48Z</updated>
	<author>
		<name>Juhani Ränkimies-2</name>
	</author>
	<content type="html">I've had similar problems on windows with mssql2008. The behaviour
&lt;br&gt;wasn't identical, but with luck your patch fixes it in my setup too.
&lt;br&gt;&lt;br&gt;I'll definitely have a look. It'll take a while though, as setting up
&lt;br&gt;a build env in windows is laborious and I've got my hands full
&lt;br&gt;already.
&lt;br&gt;&lt;br&gt;Thanks,
&lt;br&gt;-juhani
&lt;br&gt;&lt;br&gt;&lt;br&gt;On Fri, Oct 9, 2009 at 8:47 PM, Andrew Thompson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25831764&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;andrew@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Hi,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; I've been using the ODBC application against a unixodbc/mysql setup for
&lt;br&gt;&amp;gt; a while now and its been bothering me that ANY SQL error always returns
&lt;br&gt;&amp;gt; {port_exit,could_not_access_column_count} from the erlang side. I
&lt;br&gt;&amp;gt; decided to dig into the code and figure out why and this is what I
&lt;br&gt;&amp;gt; discovered:
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; In the get_diagnos function of odbcserver.c every time SQLGetDiagRec is
&lt;br&gt;&amp;gt; called diagnos.sqlState is passed in as the target to write the returned
&lt;br&gt;&amp;gt; SQLSTATE into. However, when you've run out of diagnostic information
&lt;br&gt;&amp;gt; and SQLGetDiagRec() returns something other than SQL_SUCCESS, the value
&lt;br&gt;&amp;gt; of diagnos.sqlState *still* gets changed (at least in my case) to 00000,
&lt;br&gt;&amp;gt; which is, of course, the INFO SQLSTATE. This causes the check in
&lt;br&gt;&amp;gt; db_query against INFO to succeed when it should be failing and since in
&lt;br&gt;&amp;gt; my case the error message didn't begin with 'error' it falls through
&lt;br&gt;&amp;gt; encode_result which is where the EXIT_COLS comes in. Attached is a patch
&lt;br&gt;&amp;gt; to resolve this problem by only updating diagnos.sqlState when
&lt;br&gt;&amp;gt; SQLGetDiagRec returns success.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; I don't know if all ODBC implementations behave this way, but I'd assume
&lt;br&gt;&amp;gt; that the SQLSTATE from a failed SQLGetDiagRec can safely be ignored in
&lt;br&gt;&amp;gt; all cases.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Thanks,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Andrew
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;/div&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25831764.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25825264</id>
	<title>PATCH: ODBC application discarding sqlstate in get_diagnos function</title>
	<published>2009-10-09T10:47:43Z</published>
	<updated>2009-10-09T10:47:43Z</updated>
	<author>
		<name>Andrew Thompson-15</name>
	</author>
	<content type="html">Hi,
&lt;br&gt;&lt;br&gt;I've been using the ODBC application against a unixodbc/mysql setup for
&lt;br&gt;a while now and its been bothering me that ANY SQL error always returns
&lt;br&gt;{port_exit,could_not_access_column_count} from the erlang side. I
&lt;br&gt;decided to dig into the code and figure out why and this is what I
&lt;br&gt;discovered:
&lt;br&gt;&lt;br&gt;In the get_diagnos function of odbcserver.c every time SQLGetDiagRec is
&lt;br&gt;called diagnos.sqlState is passed in as the target to write the returned
&lt;br&gt;SQLSTATE into. However, when you've run out of diagnostic information
&lt;br&gt;and SQLGetDiagRec() returns something other than SQL_SUCCESS, the value
&lt;br&gt;of diagnos.sqlState *still* gets changed (at least in my case) to 00000,
&lt;br&gt;which is, of course, the INFO SQLSTATE. This causes the check in
&lt;br&gt;db_query against INFO to succeed when it should be failing and since in
&lt;br&gt;my case the error message didn't begin with 'error' it falls through
&lt;br&gt;encode_result which is where the EXIT_COLS comes in. Attached is a patch
&lt;br&gt;to resolve this problem by only updating diagnos.sqlState when
&lt;br&gt;SQLGetDiagRec returns success.
&lt;br&gt;&lt;br&gt;I don't know if all ODBC implementations behave this way, but I'd assume
&lt;br&gt;that the SQLSTATE from a failed SQLGetDiagRec can safely be ignored in
&lt;br&gt;all cases.
&lt;br&gt;&lt;br&gt;Thanks,
&lt;br&gt;&lt;br&gt;Andrew
&lt;br&gt;&lt;br /&gt;--- c_src/odbcserver.c.orig	2009-10-09 13:11:01.000000000 -0400
&lt;br&gt;+++ c_src/odbcserver.c	2009-10-09 13:20:21.000000000 -0400
&lt;br&gt;@@ -2451,6 +2451,7 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;SQLSMALLINT errmsg_buffer_size, record_nr, errmsg_size;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int acc_errmsg_size;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;byte *current_errmsg_pos;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;SQLCHAR current_sql_state[SQL_STATE_SIZE];
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;diagnos.error_msg[0] = 0;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;
&lt;br&gt;@@ -2463,7 +2464,7 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;/* Foreach diagnostic record in the current set of diagnostic records
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; the error message is obtained */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;for(record_nr = 1; ;record_nr++) { &amp;nbsp; &amp;nbsp;
&lt;br&gt;-	if(SQLGetDiagRec(handleType, handle, record_nr, diagnos.sqlState,
&lt;br&gt;+	if(SQLGetDiagRec(handleType, handle, record_nr, current_sql_state,
&lt;br&gt;&amp;nbsp;			 &amp;nativeError, current_errmsg_pos,
&lt;br&gt;&amp;nbsp;			 (SQLSMALLINT)errmsg_buffer_size, &amp;errmsg_size)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; != SQL_SUCCESS) {
&lt;br&gt;@@ -2471,6 +2472,9 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;&amp;nbsp;	} else {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;/* update the sqlstate in the diagnos record, because the SQLGetDiagRec
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp; &amp;nbsp; call succeeded */
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;memcpy(diagnos.sqlState, current_sql_state, SQL_STATE_SIZE);
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;errmsg_buffer_size = errmsg_buffer_size - errmsg_size;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;acc_errmsg_size = acc_errmsg_size + errmsg_size;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;current_errmsg_pos = current_errmsg_pos + errmsg_size;
&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/PATCH%3A-ODBC-application-discarding-sqlstate-in-get_diagnos-function-tp25825264p25825264.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25823367</id>
	<title>Re: Some bugfixes in ei_x_format in R13B02-1</title>
	<published>2009-10-09T08:43:10Z</published>
	<updated>2009-10-09T08:43:10Z</updated>
	<author>
		<name>Björn-Egil Dahlberg</name>
	</author>
	<content type="html">Hi Cristopher,
&lt;br&gt;&lt;br&gt;Thank your for pointing out these issues and supplying a patch for it.
&lt;br&gt;I will have a look at it as soon as I can.
&lt;br&gt;&lt;br&gt;Regards,
&lt;br&gt;Björn-Egil
&lt;br&gt;Erlang/OTP
&lt;br&gt;&lt;br&gt;christopher faulet wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Hi all,
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; the attached patch fixes some bugs in functions that build terms from
&lt;br&gt;&amp;gt; strings, called by ei_x_format and ei_x_format_wo_ver. It improves the
&lt;br&gt;&amp;gt; parsing of lists, tuples, strings, atoms and digits. The file test_ei.c
&lt;br&gt;&amp;gt; in attachement shows examples that ei_x_format doesn't parse correctly.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; In addition, I added support of hexadecimal representations of digit.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; This patch also fixes a bug in erl_call. When we use the option &amp;quot;-a 'Mod
&lt;br&gt;&amp;gt; Fun Args'&amp;quot;, the module and function are extracted and the remainings are
&lt;br&gt;&amp;gt; passed to ei_x_format_wo_ver in order to build arguments before calling
&lt;br&gt;&amp;gt; the function ei_rpc. The problem is that this function tries to replace
&lt;br&gt;&amp;gt; all ~a,~s,~i... But in this context, it's a mistake. To avoid this
&lt;br&gt;&amp;gt; behaviour, I added a new function, ei_x_parse, that transforms a string
&lt;br&gt;&amp;gt; in erlang term without any replacement. Here is an example:
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; &amp;nbsp; * the following command returns an error instead of [&amp;quot;test&amp;quot;]:
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; erl_call -sname bug_ei -s -a 'io_lib format [&amp;quot;~p&amp;quot;, [test]]'
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; I only tested this patch on linux but I hope that it works on other OS.
&lt;br&gt;&amp;gt; 
&lt;br&gt;&amp;gt; Best regards,
&lt;br&gt;&amp;gt; 
&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Some-bugfixes-in-ei_x_format-in-R13B02-1-tp25822319p25823367.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25822319</id>
	<title>Some bugfixes in ei_x_format in R13B02-1</title>
	<published>2009-10-09T07:38:56Z</published>
	<updated>2009-10-09T07:38:56Z</updated>
	<author>
		<name>Christopher Faulet</name>
	</author>
	<content type="html">Hi all,
&lt;br&gt;&lt;br&gt;the attached patch fixes some bugs in functions that build terms from
&lt;br&gt;strings, called by ei_x_format and ei_x_format_wo_ver. It improves the
&lt;br&gt;parsing of lists, tuples, strings, atoms and digits. The file test_ei.c
&lt;br&gt;in attachement shows examples that ei_x_format doesn't parse correctly.
&lt;br&gt;&lt;br&gt;In addition, I added support of hexadecimal representations of digit.
&lt;br&gt;&lt;br&gt;This patch also fixes a bug in erl_call. When we use the option &amp;quot;-a 'Mod
&lt;br&gt;Fun Args'&amp;quot;, the module and function are extracted and the remainings are
&lt;br&gt;passed to ei_x_format_wo_ver in order to build arguments before calling
&lt;br&gt;the function ei_rpc. The problem is that this function tries to replace
&lt;br&gt;all ~a,~s,~i... But in this context, it's a mistake. To avoid this
&lt;br&gt;behaviour, I added a new function, ei_x_parse, that transforms a string
&lt;br&gt;in erlang term without any replacement. Here is an example:
&lt;br&gt;&lt;br&gt;&amp;nbsp; * the following command returns an error instead of [&amp;quot;test&amp;quot;]:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; erl_call -sname bug_ei -s -a 'io_lib format [&amp;quot;~p&amp;quot;, [test]]'
&lt;br&gt;&lt;br&gt;I only tested this patch on linux but I hope that it works on other OS.
&lt;br&gt;&lt;br&gt;Best regards,
&lt;br&gt;-- 
&lt;br&gt;Christopher Faulet &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25822319&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;christopher.faulet@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br /&gt;--- lib/erl_interface/include/ei.h.orig	2009-10-06 21:45:09.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/include/ei.h	2009-10-06 21:46:22.000000000 +0200
&lt;br&gt;@@ -500,6 +500,7 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_format(ei_x_buff* x, const char* fmt, ...);
&lt;br&gt;&amp;nbsp;int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ...);
&lt;br&gt;+int ei_x_parse(ei_x_buff *x, const char* str);
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_new(ei_x_buff* x);
&lt;br&gt;&amp;nbsp;int ei_x_new_with_version(ei_x_buff* x);
&lt;br&gt;--- lib/erl_interface/src/prog/erl_call.c.orig	2009-10-06 21:46:10.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/src/prog/erl_call.c	2009-10-07 23:00:11.000000000 +0200
&lt;br&gt;@@ -562,7 +562,7 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ei_x_new(&amp;e);		/* No version to ei_rpc() */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp; &amp;nbsp;if (ei_x_format_wo_ver(&amp;e, args) &amp;lt; 0) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;if (ei_x_parse(&amp;e, args) &amp;lt; 0) {
&lt;br&gt;&amp;nbsp;	 &amp;nbsp;/* FIXME no error message and why -1 ? */
&lt;br&gt;&amp;nbsp;	 &amp;nbsp;exit(-1);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;--- lib/erl_interface/src/encode/encode_atom.c.orig	2009-10-06 21:45:46.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/src/encode/encode_atom.c	2009-10-07 22:59:50.000000000 +0200
&lt;br&gt;@@ -28,6 +28,7 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_encode_atom_len(char *buf, int *index, const char *p, int len)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;+ &amp;nbsp;int i;
&lt;br&gt;&amp;nbsp; &amp;nbsp;char *s = buf + *index;
&lt;br&gt;&amp;nbsp; &amp;nbsp;char *s0 = s;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;@@ -35,14 +36,18 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp;if (len &amp;gt; MAXATOMLEN)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;len = MAXATOMLEN;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- &amp;nbsp;if (!buf) s += 3;
&lt;br&gt;+ &amp;nbsp;if (!buf) s += 3 + len;
&lt;br&gt;&amp;nbsp; &amp;nbsp;else {
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;put8(s,ERL_ATOM_EXT);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;put16be(s,len);
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;memmove(s,p,len); /* unterminated string */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (i = 0; i &amp;lt; len; ++i) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;if (p[i] != '\\' || p[i-1] == '\\')
&lt;br&gt;+	put8(s, p[i]);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;else
&lt;br&gt;+	++len;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp; &amp;nbsp;}
&lt;br&gt;- &amp;nbsp;s += len;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp;*index += s-s0; 
&lt;br&gt;&amp;nbsp;
&lt;br&gt;--- lib/erl_interface/src/encode/encode_string.c.orig	2009-10-06 21:45:58.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/src/encode/encode_string.c	2009-10-07 22:59:42.000000000 +0200
&lt;br&gt;@@ -44,14 +44,18 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;} else if (len &amp;lt;= 0xffff) {
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (!buf) {
&lt;br&gt;-	s += 3;
&lt;br&gt;+	s += 3 + len;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;} else {
&lt;br&gt;&amp;nbsp;	put8(s,ERL_STRING_EXT);
&lt;br&gt;&amp;nbsp;	put16be(s,len);
&lt;br&gt;-	memmove(s,p,len);	/* unterminated string */
&lt;br&gt;- &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;- &amp;nbsp; &amp;nbsp; &amp;nbsp;s += len;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+	for (i = 0; i &amp;lt; len; ++i) {
&lt;br&gt;+	 &amp;nbsp;if (p[i] != '\\' || p[i-1] == '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;put8(s, p[i]);
&lt;br&gt;+	 &amp;nbsp;else
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++len;
&lt;br&gt;+	}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;} else {
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (!buf) {
&lt;br&gt;@@ -62,8 +66,12 @@
&lt;br&gt;&amp;nbsp;	put32be(s,len);
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;	for (i=0; i&amp;lt;len; i++) {
&lt;br&gt;-	 &amp;nbsp;put8(s,ERL_SMALL_INTEGER_EXT);
&lt;br&gt;-	 &amp;nbsp;put8(s,p[i]);
&lt;br&gt;+	 &amp;nbsp;if (p[i] != '\\' || p[i-1] == '\\') {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;put8(s,ERL_SMALL_INTEGER_EXT);
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;put8(s,p[i]);
&lt;br&gt;+	 &amp;nbsp;}
&lt;br&gt;+	 &amp;nbsp;else
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++len;
&lt;br&gt;&amp;nbsp;	}
&lt;br&gt;&amp;nbsp;	put8(s,ERL_NIL_EXT);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;--- lib/erl_interface/src/misc/ei_x_encode.c.orig	2009-10-06 21:45:34.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/src/misc/ei_x_encode.c	2009-10-07 22:59:22.000000000 +0200
&lt;br&gt;@@ -93,7 +93,13 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_encode_string(ei_x_buff* x, const char* s)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;- &amp;nbsp; &amp;nbsp;return ei_x_encode_string_len(x, s, strlen(s));
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;int len, i;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (i = 0, len = 0; s[i] != 0; ++i) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (s[i] != '\\' || s[i-1] == '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++len;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;return ei_x_encode_string_len(x, s, len);
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)
&lt;br&gt;@@ -197,7 +203,13 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_encode_atom(ei_x_buff* x, const char* s)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;- &amp;nbsp; &amp;nbsp;return ei_x_encode_atom_len(x, s, strlen(s));
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;int len, i;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (i = 0, len = 0; s[i] != 0; ++i) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (s[i] != '\\' || s[i-1] == '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++len;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;return ei_x_encode_atom_len(x, s, len);
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len)
&lt;br&gt;--- lib/erl_interface/src/misc/ei_format.c.orig	2009-10-06 21:45:20.000000000 +0200
&lt;br&gt;+++ lib/erl_interface/src/misc/ei_format.c	2009-10-07 22:58:54.000000000 +0200
&lt;br&gt;@@ -71,29 +71,29 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int res;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ei_x_buff x2;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;while (isspace((int)*p))
&lt;br&gt;-	++p;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (; isspace((int)*p); ++p);
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;switch (*p) {
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case '~':
&lt;br&gt;&amp;nbsp;	res = pformat(&amp;p, args, x);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case '[':
&lt;br&gt;&amp;nbsp;	res = ei_x_new(&amp;x2);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;+	if (res != -1)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = plist(&amp;p, args, &amp;x2, 0);
&lt;br&gt;&amp;nbsp;	if (res &amp;gt; 0)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ei_x_encode_list_header(x, res);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;+	if (res != -1)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ei_x_append(x, &amp;x2);
&lt;br&gt;&amp;nbsp;	ei_x_free(&amp;x2);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case '{':
&lt;br&gt;&amp;nbsp;	res = ei_x_new(&amp;x2);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;+	if (res != -1)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ptuple(&amp;p, args, &amp;x2, 0);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;+	if (res != -1)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ei_x_encode_tuple_header(x, res);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;+	if (res != -1)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ei_x_append(x, &amp;x2);
&lt;br&gt;&amp;nbsp;	ei_x_free(&amp;x2);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;@@ -104,7 +104,7 @@
&lt;br&gt;&amp;nbsp;	res = pquotedatom(&amp;p, x);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;default:
&lt;br&gt;-	if (isdigit((int)*p))
&lt;br&gt;+	if (*p == '-' || *p == '+' || isdigit((int)*p))
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = pdigit(&amp;p, x);
&lt;br&gt;&amp;nbsp;	else if (islower((int)*p))
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = patom(&amp;p, x);
&lt;br&gt;@@ -115,6 +115,7 @@
&lt;br&gt;&amp;nbsp;	Variables
&lt;br&gt;&amp;nbsp;	*/
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;*fmt = p;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;@@ -123,49 +124,58 @@
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;const char* start = *fmt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;char c;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;int len;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;for (;;) {
&lt;br&gt;-	c = *(*fmt)++;
&lt;br&gt;-	if (isalnum((int) c) || (c == '_') || (c == '@'))
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;continue;
&lt;br&gt;-	else
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (;; ++(*fmt)) {
&lt;br&gt;+	c = **fmt;
&lt;br&gt;+	if (!isalnum((int)c) &amp;&amp; c != '_' &amp;&amp; c != '@')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;- &amp;nbsp; &amp;nbsp;--(*fmt);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;len = *fmt - start;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;/* FIXME why truncate atom name and not fail?! */
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (len &amp;gt; MAXATOMLEN)
&lt;br&gt;-	len = MAXATOMLEN;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;return ei_x_encode_atom_len(x, start, len);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;return ei_x_encode_atom_len(x, start, *fmt - start);
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;/* Check if integer or float */
&lt;br&gt;&amp;nbsp;static int pdigit(const char** fmt, ei_x_buff* x)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;- &amp;nbsp; &amp;nbsp;const char* start = *fmt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;char c;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;int len, dotp=0;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;const char* p = *fmt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;char* endp;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;int is_double, base = 10;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;double d;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;long l;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;for (;;) {
&lt;br&gt;-	c = *(*fmt)++;
&lt;br&gt;-	if (isdigit((int)c))
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;continue;
&lt;br&gt;-	else if (!dotp &amp;&amp; (c == '.')) {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;dotp = 1;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;continue;
&lt;br&gt;-	} else
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* skip the sign, if any */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (*p == '-' || *p == '+')
&lt;br&gt;+	++p;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* is double or not ? */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (is_double = 0;; ++p) {
&lt;br&gt;+	if (*p == '.') {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;is_double = 1;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;+	}
&lt;br&gt;+	else if (*p == 'x' || *p == 'X')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;base = 16;
&lt;br&gt;+	else if (base == 10 &amp;&amp; !isdigit((int)*p))
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;+	else if (base == 16 &amp;&amp; !isxdigit((int)*p))
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;} 
&lt;br&gt;- &amp;nbsp; &amp;nbsp;--(*fmt);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;len = *fmt - start;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (dotp) {
&lt;br&gt;-	sscanf(start, &amp;quot;%lf&amp;quot;, &amp;d);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;errno = 0;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* convert and encode a double value */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (is_double) {
&lt;br&gt;+	d = strtod(*fmt, &amp;endp);
&lt;br&gt;+	if (errno == ERANGE)
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;return -1;
&lt;br&gt;+	*fmt = endp;
&lt;br&gt;&amp;nbsp;	return ei_x_encode_double(x, d);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;} else {
&lt;br&gt;-	sscanf(start, &amp;quot;%ld&amp;quot;, &amp;l);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* convert and encode a long value */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;else {
&lt;br&gt;+	l = strtol(*fmt, &amp;endp, base);
&lt;br&gt;+	if (errno == ERANGE)
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;return -1;
&lt;br&gt;+	*fmt = endp;
&lt;br&gt;&amp;nbsp;	return ei_x_encode_long(x, l);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;@@ -174,22 +184,24 @@
&lt;br&gt;&amp;nbsp;static int pstring(const char** fmt, ei_x_buff* x)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;const char* start = ++(*fmt); /* skip first quote */
&lt;br&gt;- &amp;nbsp; &amp;nbsp;char c;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;int res;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;for (;;) {
&lt;br&gt;-	c = *(*fmt)++;
&lt;br&gt;-	if (c == '\0')
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;char c, p;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;int res, escape;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* go to the end of string and count the number of escape chars */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (escape = 0;; ++(*fmt)) {
&lt;br&gt;+	p = *((*fmt)-1);
&lt;br&gt;+	c = **fmt;
&lt;br&gt;+	if (!c)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;return -1;
&lt;br&gt;-	if (c == '&amp;quot;') {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;if (*((*fmt)-1) == '\\')
&lt;br&gt;-		continue;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;else
&lt;br&gt;-		break;
&lt;br&gt;-	} else
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;continue;
&lt;br&gt;+	else if (c == '\\' &amp;&amp; p != '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++escape;
&lt;br&gt;+	else if (c == '&amp;quot;' &amp;&amp; p != '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;- &amp;nbsp; &amp;nbsp;res = ei_x_encode_string_len(x, start, *fmt - start - 1);
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* encode the string */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;res = ei_x_encode_string_len(x, start, *fmt - start - escape);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;++(*fmt); /* skip last quote */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;@@ -197,27 +209,29 @@
&lt;br&gt;&amp;nbsp;static int pquotedatom(const char** fmt, ei_x_buff* x)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;const char* start = ++(*fmt); /* skip first quote */
&lt;br&gt;- &amp;nbsp; &amp;nbsp;char c;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;int res;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;for (;;) {
&lt;br&gt;-	c = *(*fmt)++;
&lt;br&gt;-	if (c == 0)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;char c, p;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;int res, escape;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* go to the end of atom and count the number of escape chars */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (escape = 0;; ++(*fmt)) {
&lt;br&gt;+	p = *((*fmt)-1);
&lt;br&gt;+	c = **fmt;
&lt;br&gt;+	if (!c)
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;return -1;
&lt;br&gt;-	if (c == '\'') {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;if (*((*fmt)-1) == '\\')
&lt;br&gt;-		continue;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;else
&lt;br&gt;-		break;
&lt;br&gt;-	} else 
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;continue;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;} 
&lt;br&gt;- &amp;nbsp; &amp;nbsp;res = ei_x_encode_atom_len(x, start, *fmt - start - 1);
&lt;br&gt;+	else if (c == '\'' &amp;&amp; p != '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;break;
&lt;br&gt;+	else if (c == '\\' &amp;&amp; &amp;nbsp;p != '\\')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++escape;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* encode the string */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;res = ei_x_encode_atom_len(x, start, *fmt - start - escape);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;++(*fmt); /* skip last quote */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- /* 
&lt;br&gt;+ /*
&lt;br&gt;&amp;nbsp; &amp;nbsp;* The format letters are:
&lt;br&gt;&amp;nbsp; &amp;nbsp;* &amp;nbsp; a &amp;nbsp;- &amp;nbsp;An atom
&lt;br&gt;&amp;nbsp; &amp;nbsp;* &amp;nbsp; s &amp;nbsp;- &amp;nbsp;A string
&lt;br&gt;@@ -230,76 +244,89 @@
&lt;br&gt;&amp;nbsp;static int pformat(const char** fmt, union arg** args, ei_x_buff* x)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int res = 0;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* Return an error if there are no args (e.g. for an ei_x_parse call) */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (args == NULL)
&lt;br&gt;+ &amp;nbsp; 	return -1;
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;++(*fmt);	/* skip tilde */
&lt;br&gt;- &amp;nbsp; &amp;nbsp;switch (*(*fmt)++) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;switch (**fmt) {
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'a': 
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_atom(x, (*args)-&amp;gt;s);
&lt;br&gt;-	(*args)++;
&lt;br&gt;+	++(*args);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 's':
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_string(x, (*args)-&amp;gt;s);
&lt;br&gt;-	(*args)++;
&lt;br&gt;+	++(*args);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'i':
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_long(x, (*args)-&amp;gt;l);
&lt;br&gt;-	(*args)++;
&lt;br&gt;+	++(*args);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'l':
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_long(x, (*args)-&amp;gt;l);
&lt;br&gt;-	(*args)++;
&lt;br&gt;+	++(*args);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'u':
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_ulong(x, (*args)-&amp;gt;u);
&lt;br&gt;-	(*args)++;
&lt;br&gt;+	++(*args);
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'f': &amp;nbsp; &amp;nbsp; /* float is expanded to double (C calling conventions) */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case 'd':
&lt;br&gt;&amp;nbsp;	res = ei_x_encode_double(x, (*args)-&amp;gt;d);
&lt;br&gt;-	(*args)++;
&lt;br&gt;-	break;	
&lt;br&gt;+	++(*args);
&lt;br&gt;+	break; 
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;default:
&lt;br&gt;&amp;nbsp;	res = -1;
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;++(*fmt); /* skip char after the tilde */
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;/* encode a tuple */
&lt;br&gt;&amp;nbsp;static int ptuple(const char** fmt, union arg** args, ei_x_buff* x, int size)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;const char *p = *fmt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;const char delimiter = **fmt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int res = 0;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;const char* p = *fmt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;char after = *p++;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (after == '}') {
&lt;br&gt;-	*fmt = p;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (!(*p))
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return size;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* ending of tuple */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (delimiter == '}')
&lt;br&gt;&amp;nbsp;	return size;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;}
&lt;br&gt;- &amp;nbsp; &amp;nbsp;while (isspace((int)*p))
&lt;br&gt;-	++p;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;switch (*p++) {
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case '}':
&lt;br&gt;-	if (after == ',')
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* skip white-space chars */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (++p; isspace((int)*p); ++p);
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;switch (delimiter) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case '{': /* beginning of tuple */
&lt;br&gt;+	if (*p == ',')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	else
&lt;br&gt;+	else if (*p == '}')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = size;
&lt;br&gt;+	else if ((res = eiformat(&amp;p, args, x)) != -1) {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++size;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;for (; isspace((int)*p); ++p);
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;res = ptuple(&amp;p, args, x, size);
&lt;br&gt;+	}
&lt;br&gt;+	p = (*p ? p+1 : p); /* skip the '}', if any */
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case ',':
&lt;br&gt;-	if (after == ',' || after == '{')
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case ',': /* next term of tuple */
&lt;br&gt;+	if (*p == ',' || *p == '}')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	else
&lt;br&gt;+	else if ((res = eiformat(&amp;p, args, x)) != -1) {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++size;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;for (; isspace((int)*p); ++p);
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = ptuple(&amp;p, args, x, size);
&lt;br&gt;+	}
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;default:
&lt;br&gt;-	--p;
&lt;br&gt;-	res = eiformat(&amp;p, args, x);
&lt;br&gt;-	if (res &amp;gt;= 0)
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;res = ptuple(&amp;p, args, x, size + 1);
&lt;br&gt;-	break;
&lt;br&gt;-	/*
&lt;br&gt;-	Variables
&lt;br&gt;-	*/
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;default: /* wrong delimiter */
&lt;br&gt;+	res = -1;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;*fmt = p;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;@@ -307,54 +334,63 @@
&lt;br&gt;&amp;nbsp;/* encode a list */
&lt;br&gt;&amp;nbsp;static int plist(const char** fmt, union arg** args, ei_x_buff* x, int size)
&lt;br&gt;&amp;nbsp;{
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;const char *p = *fmt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;const char delimiter = **fmt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int res = 0;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;const char* p = *fmt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;char after = *p++;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (after == ']')
&lt;br&gt;-	--p;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;while (isspace((int)*p))
&lt;br&gt;-	++p;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;switch (*p++) {
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case ']':
&lt;br&gt;-	if (after == ',')
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (!*p)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return size;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* end of list */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (delimiter == ']') {
&lt;br&gt;+	ei_x_encode_empty_list(x);
&lt;br&gt;+	return size;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* skip white-space chars */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;for (++p; isspace((int)*p); ++p);
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;switch (delimiter) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case '[': /* beginning of list */
&lt;br&gt;+	if (*p == ',' || *p == '|')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	else {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;if (after != '|')
&lt;br&gt;-		ei_x_encode_empty_list(x);
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;res = size;
&lt;br&gt;+	else if (*p == ']')
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;res = ei_x_encode_empty_list(x);
&lt;br&gt;+	else if ((res = eiformat(&amp;p, args, x)) != -1) {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++size;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;for (; isspace((int)*p); ++p);
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;res = plist(&amp;p, args, x, size);
&lt;br&gt;&amp;nbsp;	}
&lt;br&gt;+	p = (*p ? p+1 : p); /* skip the ']', if any */
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case '|':
&lt;br&gt;-	if (after == '|' || after == ',')
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case ',': /* next term of list */
&lt;br&gt;+	if (*p == ',' || *p == '|' || *p == ']')
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	else
&lt;br&gt;+	else if ((res = eiformat(&amp;p, args, x)) != -1) {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;++size;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;for (; isspace((int)*p); ++p);
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = plist(&amp;p, args, x, size);
&lt;br&gt;+	}
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case ',':
&lt;br&gt;-	if (after == '|' || after == ',')
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	else
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case '|': /* last term of list */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (*p == '[') {
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;res = plist(&amp;p, args, x, size);
&lt;br&gt;-	break;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;default:
&lt;br&gt;-	--p;
&lt;br&gt;-	res = eiformat(&amp;p, args, x);
&lt;br&gt;-	++size;
&lt;br&gt;-	if (res &amp;gt;= 0) {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;if (after == '|') {
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;while (isspace((int)*p))
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;++p;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;res = ((!res) ? 1 : res); /* if an empty sublist ? */
&lt;br&gt;+	}
&lt;br&gt;+	else {
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;if ((res = eiformat(&amp;p, args, x)) != -1) {
&lt;br&gt;+		for (; isspace((int)*p); ++p);
&lt;br&gt;&amp;nbsp;		if (*p != ']')
&lt;br&gt;&amp;nbsp;		 &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;} else
&lt;br&gt;-		res = plist(&amp;p, args, x, size);
&lt;br&gt;-	}
&lt;br&gt;+		else
&lt;br&gt;+		 &amp;nbsp; &amp;nbsp;res = plist(&amp;p, args, x, size);
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+	 &amp;nbsp;}
&lt;br&gt;&amp;nbsp;	break;
&lt;br&gt;-	/*
&lt;br&gt;-	Variables
&lt;br&gt;-	*/
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;default: /* wrong delimiter */
&lt;br&gt;+	res = -1;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;*fmt = p;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;@@ -429,17 +465,21 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int res;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;res = ei_x_encode_version(x);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (res &amp;lt; 0) return res;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (res == -1) return res;
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;va_start(ap, fmt);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;res = read_args(fmt,ap,&amp;args);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;saved_args = args;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;va_end(ap);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (res &amp;lt; 0) {
&lt;br&gt;-	return -1;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (res == -1) {
&lt;br&gt;+	return res;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;res = eiformat(&amp;fmt, &amp;args, x);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* We must be at the end of string */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (*fmt) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ei_free(saved_args);
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;@@ -456,11 +496,29 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;res = read_args(fmt,ap,&amp;args);
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;saved_args = args;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;va_end(ap);
&lt;br&gt;- &amp;nbsp; &amp;nbsp;if (res &amp;lt; 0) {
&lt;br&gt;-	return -1;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (res == -1) {
&lt;br&gt;+	return res;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;res = eiformat(&amp;fmt, &amp;args, x);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;/* We must be at the end of string */
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;if (*fmt) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;}
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ei_free(saved_args);
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return res;
&lt;br&gt;&amp;nbsp;}
&lt;br&gt;+
&lt;br&gt;+int ei_x_parse(ei_x_buff *x, const char* str)
&lt;br&gt;+{
&lt;br&gt;+ &amp;nbsp;int res;
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp;res = eiformat(&amp;str, NULL, x);
&lt;br&gt;+
&lt;br&gt;+ &amp;nbsp;/* We must be at the end of string */
&lt;br&gt;+ &amp;nbsp;if (*str) {
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;res = -1;
&lt;br&gt;+ &amp;nbsp;}
&lt;br&gt;+ &amp;nbsp;return res;
&lt;br&gt;+}
&lt;br&gt;&lt;br /&gt;/*
&lt;br&gt;&amp;nbsp; gcc -I/usr/lib/erlang/lib/erl_interface-3.6.3/include \
&lt;br&gt;&amp;nbsp; -L/usr/lib/erlang/lib/erl_interface-3.6.3/lib \
&lt;br&gt;&amp;nbsp; test_ei.c -o test_ei_ko -lei_st
&lt;br&gt;*/
&lt;br&gt;&lt;br&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;br&gt;#include &amp;lt;stdlib.h&amp;gt;
&lt;br&gt;#include &amp;lt;string.h&amp;gt;
&lt;br&gt;&lt;br&gt;#include &amp;lt;ei.h&amp;gt;
&lt;br&gt;&lt;br&gt;static unsigned int &amp;nbsp; &amp;nbsp;success = 0;
&lt;br&gt;static unsigned int &amp;nbsp; &amp;nbsp;failure = 0;
&lt;br&gt;&lt;br&gt;#define TEST(expected, str, arg) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; { &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; char &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;*result = NULL; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; int &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;res, index = 0; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; ei_x_buff &amp;nbsp; &amp;nbsp;x; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; ei_x_new(&amp;x); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; res = ei_x_format(&amp;x, str, arg); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; if (res != -1) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; { &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ei_decode_version(x.buff, &amp;index, (int[]){0}); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ei_s_print_term(&amp;result, &amp;nbsp;x.buff, &amp;index); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; } &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; else &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; result = strdup(&amp;quot;error&amp;quot;); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; ei_x_free(&amp;x); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; fprintf(stdout, &amp;quot;%-15s&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (!strcmp(result, expected)) ? &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (success++, &amp;quot;[SUCCEEDED]&amp;quot;) : (failure++, &amp;quot;[FAILED]&amp;quot;)); &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; if (arg) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; fprintf(stdout, &amp;quot;- Test: %-6s,%-8s&amp;quot;, str, arg); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; else &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; fprintf(stdout, &amp;quot;- Test: %-15s&amp;quot;, str); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;\
&lt;br&gt;&amp;nbsp; &amp;nbsp; fprintf(stdout, &amp;quot;- Expected: %-15s&amp;quot;, expected); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; fprintf(stdout, &amp;quot;- Result: %-15s\n&amp;quot;, result); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; &amp;nbsp; free(result); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;&amp;nbsp; }
&lt;br&gt;&lt;br&gt;&lt;br&gt;int
&lt;br&gt;main(int argc, char *argv[])
&lt;br&gt;{
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nTUPLE:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{a, b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{a,b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{a, b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{a, b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{a, b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{a ,b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{a, b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{a , b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{a ,}b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{a ,]b}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{a}b&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{a, {b ,}}&amp;quot;, &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{a, {}b}&amp;quot;, &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{{}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{{}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{{a}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;{{a}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{{a}, {b}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;{{a},{b}}&amp;quot;, &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;{{a, b}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;{{a,b}}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nLIST:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[,]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[ ,]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[, ]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[ , ]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[|]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[ |]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[| ]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[ | ]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a|]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[,a]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[|a]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[a]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a|[]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;[[]|[]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[[a]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[[a]|[]]&amp;quot;, &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a], b]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;[[a]|[b]]&amp;quot;, &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a], [b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;[[a] ,[b]]&amp;quot;, &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[a, b]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;[a ,b]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a]b&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[a | b]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a|b]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a | b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[[a|b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a, b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;[[a|[b]]]&amp;quot;, &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[[a, b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;[[a,b]]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[a, b, c]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a,b|[c]]&amp;quot;, &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;[a, b | c]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;[a,b|c]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a|[b]|[c]]&amp;quot;, &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;[a|b|c]&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nATOM:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;a'any'&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;a{any}&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;a\\1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;a1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;'a\\1'&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nSTRING:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;\&amp;quot;str\&amp;quot;any&amp;quot;, &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;\&amp;quot;str\&amp;quot;{any}&amp;quot;, NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;\&amp;quot;str1\&amp;quot;&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;\&amp;quot;str\\1\&amp;quot;&amp;quot;, &amp;nbsp; NULL);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nDIGIT:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;-1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;-1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;+1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;1any&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;-1.000000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;-1.0&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;1.000000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;+1.0&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;1.0any&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;100.000000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;1.0e2&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nDIGIT HEXA EXTENSION:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;0x&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;10&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;+0xa&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;-10.500000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;-0Xa.8&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;21.000000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;0xa.8p1&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;42.000000&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;0xa.8P2&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;NULL);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\nVARG:\n&amp;quot;);
&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;%s\n&amp;quot;,&amp;quot;----------------------------------&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;error&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;~aany&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;toto&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;atoma&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;~a&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;toto\\a&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;'atom\\a'&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;~a&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;toto\\\\a&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;\&amp;quot;stra\&amp;quot;&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;~s&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;str\\a&amp;quot;);
&lt;br&gt;&amp;nbsp; TEST(&amp;quot;\&amp;quot;str\\a\&amp;quot;&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;quot;~s&amp;quot;, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;str\\\\a&amp;quot;);
&lt;br&gt;&lt;br&gt;&amp;nbsp; fprintf(stdout, &amp;quot;\n ==&amp;gt; SUCCESS: %-5d FAILURE: %d\n&amp;quot;, success, failure);
&lt;br&gt;&lt;br&gt;&amp;nbsp; return 0;
&lt;br&gt;}
&lt;br&gt;&lt;br /&gt; &lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;signature.asc&lt;/strong&gt; (268 bytes) &lt;a href=&quot;http://old.nabble.com/attachment/25822319/0/signature.asc&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Some-bugfixes-in-ei_x_format-in-R13B02-1-tp25822319p25822319.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25822198</id>
	<title>Epp Bugfix and macros overloading</title>
	<published>2009-10-09T07:31:44Z</published>
	<updated>2009-10-09T07:31:44Z</updated>
	<author>
		<name>Christopher Faulet</name>
	</author>
	<content type="html">Hi all,
&lt;br&gt;&lt;br&gt;Here are two patches for the module epp in R13B02-1.
&lt;br&gt;&lt;br&gt;* The first one fixes a bug in the function scan_undef. The dict that
&lt;br&gt;helps to find circular macros is not correctly updated. Here is an example:
&lt;br&gt;&lt;br&gt;=============================
&lt;br&gt;-module(test).
&lt;br&gt;-export([test/0]).
&lt;br&gt;&lt;br&gt;-define(FOO(X), ?BAR(X)).
&lt;br&gt;-define(BAR(X), ?FOO(X)).
&lt;br&gt;-undef(FOO).
&lt;br&gt;&lt;br&gt;test() -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; ?BAR(1).
&lt;br&gt;=============================
&lt;br&gt;&lt;br&gt;On the last line, the preprocessor should found that 'FOO' is undefined.
&lt;br&gt;But, with the current version, it finds a cycle between FOO and BAR.
&lt;br&gt;&lt;br&gt;* The second patch includes the first one and adds support of multiple
&lt;br&gt;definitions for macros in the module epp (i.e. with the same name but
&lt;br&gt;with different arities). This feature wouldn't break any code (I hope so
&lt;br&gt;:) and might be usefull.
&lt;br&gt;&lt;br&gt;Here is an simple example that uses it:
&lt;br&gt;&lt;br&gt;=============================
&lt;br&gt;-module(test).
&lt;br&gt;&lt;br&gt;-export([test/0]).
&lt;br&gt;&lt;br&gt;-define(MY_MACRO(), &amp;nbsp; &amp;nbsp;foo).
&lt;br&gt;-define(MY_MACRO, &amp;nbsp; &amp;nbsp; &amp;nbsp;bar).
&lt;br&gt;-define(MY_MACRO(X,Y), {X, Y}).
&lt;br&gt;&lt;br&gt;&lt;br&gt;test() -&amp;gt; &amp;nbsp;%% return [bar, foo, foo, {foo, bar}]
&lt;br&gt;&amp;nbsp; &amp;nbsp; [
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;?MY_MACRO, &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% use the 2nd def, replaced by bar
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;?MY_MACRO(), &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% use the 1st def, replaced by foo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;?MY_MACRO(foo), &amp;nbsp; &amp;nbsp; %% use the 2nd def, replaced by bar(foo)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;?MY_MACRO(foo, bar) %% use the 3rd def, replaced by {foo,bar}
&lt;br&gt;&amp;nbsp; &amp;nbsp; ].
&lt;br&gt;&lt;br&gt;bar(X) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; X.
&lt;br&gt;=============================
&lt;br&gt;&lt;br&gt;In this patch, we follow these rules:
&lt;br&gt;&lt;br&gt;- the overloading of predefined macros (?MODULE, ?LINE, ...) is forbidden
&lt;br&gt;- the directive '-undef' removes all definitions of a macro
&lt;br&gt;- when a macro is called, the preprocessor tries to match the definition
&lt;br&gt;with the right number of arguments. If it fails, it uses the constant
&lt;br&gt;definition, if there is one, else returns an error.
&lt;br&gt;- the circular definitions are checked following the previous rule.
&lt;br&gt;&lt;br&gt;It would be interesting to add this feature. What do you think about it?
&lt;br&gt;&lt;br&gt;Best regards,
&lt;br&gt;-- 
&lt;br&gt;Christopher Faulet &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25822198&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;christopher.faulet@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br /&gt;--- lib/stdlib/src/epp.erl.orig	2009-09-29 15:44:10.000000000 +0200
&lt;br&gt;+++ lib/stdlib/src/epp.erl	2009-10-05 15:05:45.000000000 +0200
&lt;br&gt;@@ -558,11 +558,11 @@
&lt;br&gt;&amp;nbsp;%% scan_undef(Tokens, UndefToken, From, EppState)
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=all_macro_uses(Macs)});
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=all_macro_uses(Macs)});
&lt;br&gt;&amp;nbsp;scan_undef(_Toks, Undef, From, St) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St).
&lt;br&gt;&lt;br /&gt;--- lib/stdlib/src/epp.erl.orig	2009-10-07 21:32:58.000000000 +0200
&lt;br&gt;+++ lib/stdlib/src/epp.erl	2009-10-07 21:47:22.000000000 +0200
&lt;br&gt;@@ -244,14 +244,15 @@
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{error,{redefine,M}};
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;Exp = erl_parse:tokens(erl_parse:abstract(Val)),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms))
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;user_predef([M|Pdm], Ms) when is_atom(M) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, Ms) of
&lt;br&gt;&amp;nbsp;	{ok,_Def} -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{error,{redefine,M}};
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;user_predef(Pdm, dict:store({atom,M}, {none,[{atom,1,true}]}, Ms))
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;user_predef(Pdm,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;dict:store({atom,M}, [{none, {none,[{atom,1,true}]}}], Ms))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;user_predef([Md|_Pdm], _Ms) -&amp;gt; {error,{bad,Md}};
&lt;br&gt;&amp;nbsp;user_predef([], Ms) -&amp;gt; {ok,Ms}.
&lt;br&gt;@@ -458,57 +459,55 @@
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% scan_define(Tokens, DefineToken, From, EppState)
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) -&amp;gt;
&lt;br&gt;+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St)
&lt;br&gt;+ &amp;nbsp;when Type =:= atom; Type =:= var -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_OldDef} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {none,macro_expansion(Toks)})
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;-		{ok, {As, Me}} -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp;{atom, M},
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp;{As, Me});
&lt;br&gt;-		_ -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;end
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_OldDef} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-			 &amp;nbsp; &amp;nbsp; {none,macro_expansion(Toks)})
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;-	{ok,_Def} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;-	error -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;-		{ok, {As, Me}} -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;-				 &amp;nbsp; &amp;nbsp; {As, Me});
&lt;br&gt;-		_ -&amp;gt;
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;-		 &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;end
&lt;br&gt;+ 	 &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% User defined macros: can be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case proplists:is_defined(none, Defs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;true -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;false -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {none, {none,macro_expansion(Toks)}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, _PreDef} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% Predefined macros: cannot be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {none, {none,macro_expansion(Toks)}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
&lt;br&gt;+ &amp;nbsp;when Type =:= atom; Type =:= var -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case catch macro_pars(Toks, []) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, {As,Me}} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Len = length(As),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find({atom,M}, St#epp.macs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% User defined macros: can be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case proplists:is_defined(Len, Defs) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;true -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;false -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St, {atom, M},
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {Len, {As, Me}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, _PreDef} -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%% Predefined macros: cannot be overloaded
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St);
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_ -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;scan_define(_Toks, Def, From, St) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
&lt;br&gt;@@ -523,13 +522,11 @@
&lt;br&gt;&amp;nbsp;%%% the information from St#epp.uses is traversed, and if a circularity
&lt;br&gt;&amp;nbsp;%%% is detected, an error message is thrown.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-scan_define_cont(F, St, M, Def) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;Ms = dict:store(M, Def, St#epp.macs),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;U = dict:store(M, macro_uses(Def), St#epp.uses),
&lt;br&gt;+scan_define_cont(F, St, M, {Arity, Def}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;U = dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;scan_toks(F, St#epp{uses=U, macs=Ms}).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-macro_uses(undefined) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;undefined;
&lt;br&gt;&amp;nbsp;macro_uses({_Args, Tokens}) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Uses0 = macro_ref(Tokens),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;lists:usort(Uses0).
&lt;br&gt;@@ -538,31 +535,27 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;[];
&lt;br&gt;&amp;nbsp;macro_ref([{'?', _}, {'?', _} | Rest]) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;macro_ref(Rest);
&lt;br&gt;-macro_ref([{'?', _}, {atom, _, A} | Rest]) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;[{atom, A} | macro_ref(Rest)];
&lt;br&gt;-macro_ref([{'?', _}, {var, _, A} | Rest]) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;[{atom, A} | macro_ref(Rest)];
&lt;br&gt;+macro_ref([{'?', _}, {Type, Lm, A} | Rest]) when Type =:= atom; Type =:= var -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;try
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Arity = count_args(Rest, Lm, A),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;[{{atom, A}, Arity} | macro_ref(Rest)]
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;catch
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;_:_ -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;macro_ref(Rest)
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;&amp;nbsp;macro_ref([_Token | Rest]) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;macro_ref(Rest).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-all_macro_uses(D0) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;L = dict:to_list(D0),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;D = dict:new(),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;add_macro_uses(L, D).
&lt;br&gt;-
&lt;br&gt;-add_macro_uses([], D) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;D;
&lt;br&gt;-add_macro_uses([{Key, Def} | Rest], D0) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;add_macro_uses(Rest, dict:store(Key, macro_uses(Def), D0)).
&lt;br&gt;-
&lt;br&gt;&amp;nbsp;%% scan_undef(Tokens, UndefToken, From, EppState)
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Uses = dict:erase({atom,M}, St#epp.uses),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=Uses});
&lt;br&gt;&amp;nbsp;scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;-			 &amp;nbsp; uses=all_macro_uses(St#epp.macs)});
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Macs = dict:erase({atom,M}, St#epp.macs),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Uses = dict:erase({atom,M}, St#epp.uses),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;scan_toks(From, St#epp{macs=Macs, uses=Uses});
&lt;br&gt;&amp;nbsp;scan_undef(_Toks, Undef, From, St) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;wait_req_scan(St).
&lt;br&gt;@@ -801,14 +794,15 @@
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;%% (Type will always be 'atom')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{Ms, U} = Ms0,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Lm = loc(MacT),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;check_uses([{Type,M}], [], U, Lm),
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Tinfo = element(2, MacT),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;case dict:find({Type,M}, Ms) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case expand_macro1(Type, Lm, M, Toks, Ms) of
&lt;br&gt;&amp;nbsp;	{ok,{none,Exp}} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;expand_macros(expand_macro(Exp, Tinfo, Toks, dict:new()), Ms0);
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;check_uses([{{Type,M}, none}], [], U, Lm),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0),
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;expand_macros(Toks1++Toks, Ms0);
&lt;br&gt;&amp;nbsp;	{ok,{As,Exp}} -&amp;gt;
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;check_uses([{{Type,M}, length(As)}], [], U, Lm),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;{Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()),
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;%%io:format(&amp;quot;Bound arguments to macro ~w (~w)~n&amp;quot;, [M,Bs]),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0);
&lt;br&gt;&amp;nbsp;	{ok,undefined} -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M}});
&lt;br&gt;@@ -816,27 +810,37 @@
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{undefined,M}})
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;-check_uses(undefined, _Anc, _U, _Lm) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;+expand_macro1(Type, Lm, M, Toks, Ms) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Arity = count_args(Toks, Lm, M),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;case dict:find({Type,M}, Ms) of
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, Defs} when is_list(Defs) -&amp;gt; %% User defined macro
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, proplists:get_value(Arity, Defs,
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; proplists:get_value(none, Defs))};
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, PreDef} -&amp;gt; %% Predefined macro
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok, PreDef};
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;error
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;check_uses([], _Anc, _U, _Lm) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;ok;
&lt;br&gt;&amp;nbsp;check_uses([M|Rest], Anc, U, Lm) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case lists:member(M, Anc) of
&lt;br&gt;&amp;nbsp;	true -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;{_, Name} = M,
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;{{_, Name},_} = M,
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;throw({error,Lm,{circular,Name}});
&lt;br&gt;&amp;nbsp;	false -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;L = get_macro_uses(M, U),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;check_uses(L, [M|Anc], U, Lm),
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;check_uses(Rest, Anc, U, Lm)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;- &amp;nbsp; &amp;nbsp;
&lt;br&gt;-get_macro_uses(M, U) -&amp;gt;
&lt;br&gt;+
&lt;br&gt;+get_macro_uses({M,Arity}, U) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;case dict:find(M, U) of
&lt;br&gt;&amp;nbsp;	error -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;[];
&lt;br&gt;&amp;nbsp;	{ok, L} -&amp;gt;
&lt;br&gt;-	 &amp;nbsp; &amp;nbsp;L
&lt;br&gt;+	 &amp;nbsp; &amp;nbsp;proplists:get_value(Arity, L, proplists:get_value(none, L, []))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% Macro expansion
&lt;br&gt;@@ -889,6 +893,26 @@
&lt;br&gt;&amp;nbsp;store_arg(_L, _M, A, Arg, Bs) -&amp;gt;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;dict:store(A, Arg, Bs).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;+%% count_args(Tokens, MacroLine, MacroName)
&lt;br&gt;+%% &amp;nbsp;Count the number of arguments in a macro call.
&lt;br&gt;+count_args([{'(', _Llp},{')',_Lrp}|_Toks], _Lm, _M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;0;
&lt;br&gt;+count_args([{'(',_Llp}|Toks0], Lm, M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{_Arg,Toks1} = macro_arg(Toks0, [], []),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;count_args(Toks1, Lm, M, 1);
&lt;br&gt;+count_args(_Toks, _Lm, _M) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;none.
&lt;br&gt;+
&lt;br&gt;+count_args([{')',_Lrp}|_Toks], _Lm, _M, NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;NbArgs;
&lt;br&gt;+count_args([{',',_Lc}|Toks0], Lm, M, NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;{_Arg,Toks1} = macro_arg(Toks0, [], []),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;count_args(Toks1, Lm, M, NbArgs+1);
&lt;br&gt;+count_args([], Lm, M, _NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{arg_error,M}});
&lt;br&gt;+count_args(_Toks, Lm, M, _NbArgs) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;throw({error,Lm,{mismatch,M}}).
&lt;br&gt;+
&lt;br&gt;&amp;nbsp;%% macro_arg([Tok], [ClosePar], [ArgTok]) -&amp;gt; {[ArgTok],[RestTok]}.
&lt;br&gt;&amp;nbsp;%% &amp;nbsp;Collect argument tokens until we hit a ',' or a ')'. We know a
&lt;br&gt;&amp;nbsp;%% &amp;nbsp;enough about syntax to recognise &amp;quot;open parentheses&amp;quot; and keep
&lt;br&gt;&lt;br /&gt; &lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;signature.asc&lt;/strong&gt; (268 bytes) &lt;a href=&quot;http://old.nabble.com/attachment/25822198/0/signature.asc&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Epp-Bugfix-and-macros-overloading-tp25822198p25822198.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25820633</id>
	<title>Re: wx_object fixes.</title>
	<published>2009-10-09T05:50:33Z</published>
	<updated>2009-10-09T05:50:33Z</updated>
	<author>
		<name>Dan Gudmundsson-2</name>
	</author>
	<content type="html">Thanks I'll have look at it.
&lt;br&gt;&lt;br&gt;/Dan
&lt;br&gt;&lt;br&gt;On Fri, Oct 9, 2009 at 1:14 PM, Mazen Harake
&lt;br&gt;&amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25820633&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;mazen.harake@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; I've attached a patch that fixes two issues with the wx_object.erl file.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; 1) I removed a pattern match in the start functions so that if a server
&lt;br&gt;&amp;gt; returns {stop, ...} in the init function it doesn't crash with a badmatch
&lt;br&gt;&amp;gt; error.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; 2) I added 2 call functions which makes it possible to call an wx_object
&lt;br&gt;&amp;gt; using the registered name that was used when creating the object. Currently
&lt;br&gt;&amp;gt; it was only possible to make a call to an object when you have the reference
&lt;br&gt;&amp;gt; and not by name.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; I have tested it in normal cases but I can't guarantee 100% bugfree fixes :D
&lt;br&gt;&amp;gt; This patch will get anyone going until these issues are fixed (or patch
&lt;br&gt;&amp;gt; applied) to the release.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; cheers,
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; /Mazen
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; --- wx_object.original.erl      2009-09-25 23:22:12.810000000 +0200
&lt;br&gt;&amp;gt; +++ wx_object.erl       2009-10-09 12:22:13.115710400 +0200
&lt;br&gt;&amp;gt; @@ -143,8 +143,7 @@
&lt;br&gt;&amp;gt;  %% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;gt;  %% new process.
&lt;br&gt;&amp;gt;  start(Mod, Args, Options) -&amp;gt;
&lt;br&gt;&amp;gt; -    {ok, Pid} = gen:start(?MODULE, nolink, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;&amp;gt; -    receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end.
&lt;br&gt;&amp;gt; +    gen_response(gen:start(?MODULE, nolink, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;  %% @spec (Name, Mod, Args, Options) -&amp;gt; wxWindow:wxWindow()
&lt;br&gt;&amp;gt;  %%   Name = {local, atom()}
&lt;br&gt;&amp;gt; @@ -155,8 +154,7 @@
&lt;br&gt;&amp;gt;  %% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;gt;  %% new process.
&lt;br&gt;&amp;gt;  start(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;&amp;gt; -    {ok, Pid} = gen:start(?MODULE, nolink, Name, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;&amp;gt; -    receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end.
&lt;br&gt;&amp;gt; +    gen_response(gen:start(?MODULE, nolink, Name, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;  %% @spec (Mod, Args, Options) -&amp;gt; wxWindow:wxWindow()
&lt;br&gt;&amp;gt;  %%   Mod = atom()
&lt;br&gt;&amp;gt; @@ -166,8 +164,7 @@
&lt;br&gt;&amp;gt;  %% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;gt;  %% new process.
&lt;br&gt;&amp;gt;  start_link(Mod, Args, Options) -&amp;gt;
&lt;br&gt;&amp;gt; -    {ok, Pid} = gen:start(?MODULE, link, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;&amp;gt; -    receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end.
&lt;br&gt;&amp;gt; +    gen_response(gen:start(?MODULE, link, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;  %% @spec (Name, Mod, Args, Options) -&amp;gt; wxWindow:wxWindow()
&lt;br&gt;&amp;gt;  %%   Name = {local, atom()}
&lt;br&gt;&amp;gt; @@ -177,9 +174,13 @@
&lt;br&gt;&amp;gt;  %%   Flag = trace | log | {logfile, File} | statistics | debug
&lt;br&gt;&amp;gt;  %% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;gt;  %% new process.
&lt;br&gt;&amp;gt; -start_link(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;&amp;gt; -    {ok, Pid} = gen:start(?MODULE, link, Name, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;&amp;gt; -    receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end.
&lt;br&gt;&amp;gt; +start_link(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;&amp;gt; +    gen_response(gen:start(?MODULE, link, Name, Mod, Args,
&lt;br&gt;&amp;gt; [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;gt; +
&lt;br&gt;&amp;gt; +gen_response({ok, Pid}) -&amp;gt;
&lt;br&gt;&amp;gt; +    receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end;
&lt;br&gt;&amp;gt; +gen_response(Reply) -&amp;gt;
&lt;br&gt;&amp;gt; +    Reply.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;  %% @spec(wxObject(), Request) -&amp;gt; term()
&lt;br&gt;&amp;gt;  %% @doc Make a call to a wx_object server.
&lt;br&gt;&amp;gt; @@ -190,7 +191,18 @@
&lt;br&gt;&amp;gt;        Res
&lt;br&gt;&amp;gt;     catch _:Reason -&amp;gt;
&lt;br&gt;&amp;gt;            erlang:error({Reason, {?MODULE, call, [Ref, Request]}})
&lt;br&gt;&amp;gt; -    end.
&lt;br&gt;&amp;gt; +    end;
&lt;br&gt;&amp;gt; +%% @spec(atom(), Request) -&amp;gt; term()
&lt;br&gt;&amp;gt; +%% @doc Make a call to a registered wx_object server
&lt;br&gt;&amp;gt; +%% Invokes handle_call(Request, From, State) in server
&lt;br&gt;&amp;gt; +call(Name, Request) when is_atom(Name) -&amp;gt;
&lt;br&gt;&amp;gt; +    try
&lt;br&gt;&amp;gt; +        {ok,Res} = gen:call(Name, '$gen_call', Request),
&lt;br&gt;&amp;gt; +        Res
&lt;br&gt;&amp;gt; +    catch _:Reason -&amp;gt;
&lt;br&gt;&amp;gt; +            erlang:error({Reason, {?MODULE, call, [Name, Request]}})
&lt;br&gt;&amp;gt; +    end.
&lt;br&gt;&amp;gt; +
&lt;br&gt;&amp;gt;  %% @spec(wxObject(), Request, integer()) -&amp;gt; term()
&lt;br&gt;&amp;gt;  %% @doc Make a call to a wx_object server.
&lt;br&gt;&amp;gt;  %% Invokes handle_call(Request, From, State) in server
&lt;br&gt;&amp;gt; @@ -200,6 +212,16 @@
&lt;br&gt;&amp;gt;        Res
&lt;br&gt;&amp;gt;     catch _:Reason -&amp;gt;
&lt;br&gt;&amp;gt;            erlang:error({Reason, {?MODULE, call, [Ref, Request, Timeout]}})
&lt;br&gt;&amp;gt; +    end;
&lt;br&gt;&amp;gt; +%% @spec(atom(), Request, integer()) -&amp;gt; term()
&lt;br&gt;&amp;gt; +%% @doc Make a call to a registered wx_object server
&lt;br&gt;&amp;gt; +%% Invokes handle_call(Request, From, State) in server
&lt;br&gt;&amp;gt; +call(Name, Request, Timeout) when is_atom(Name) -&amp;gt;
&lt;br&gt;&amp;gt; +    try
&lt;br&gt;&amp;gt; +        {ok,Res} = gen:call(Name, '$gen_call', Request, Timeout),
&lt;br&gt;&amp;gt; +        Res
&lt;br&gt;&amp;gt; +    catch _:Reason -&amp;gt;
&lt;br&gt;&amp;gt; +            erlang:error({Reason, {?MODULE, call, [Name, Request,
&lt;br&gt;&amp;gt; Timeout]}})
&lt;br&gt;&amp;gt;     end.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;  %% -----------------------------------------------------------------
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; ________________________________________________________________
&lt;br&gt;&amp;gt; erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;&amp;gt; erlang-patches (at) erlang.org
&lt;br&gt;&amp;gt;
&lt;/div&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org
&lt;br&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wx_object-fixes.-tp25819342p25820633.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25819342</id>
	<title>wx_object fixes.</title>
	<published>2009-10-09T04:14:54Z</published>
	<updated>2009-10-09T04:14:54Z</updated>
	<author>
		<name>Mazen Harake-2</name>
	</author>
	<content type="html">I've attached a patch that fixes two issues with the wx_object.erl file.
&lt;br&gt;&lt;br&gt;1) I removed a pattern match in the start functions so that if a server 
&lt;br&gt;returns {stop, ...} in the init function it doesn't crash with a 
&lt;br&gt;badmatch error.
&lt;br&gt;&lt;br&gt;2) I added 2 call functions which makes it possible to call an wx_object 
&lt;br&gt;using the registered name that was used when creating the object. 
&lt;br&gt;Currently it was only possible to make a call to an object when you have 
&lt;br&gt;the reference and not by name.
&lt;br&gt;&lt;br&gt;I have tested it in normal cases but I can't guarantee 100% bugfree 
&lt;br&gt;fixes :D
&lt;br&gt;This patch will get anyone going until these issues are fixed (or patch 
&lt;br&gt;applied) to the release.
&lt;br&gt;&lt;br&gt;cheers,
&lt;br&gt;&lt;br&gt;/Mazen
&lt;br&gt;&lt;br /&gt;--- wx_object.original.erl	2009-09-25 23:22:12.810000000 +0200
&lt;br&gt;+++ wx_object.erl	2009-10-09 12:22:13.115710400 +0200
&lt;br&gt;@@ -143,8 +143,7 @@
&lt;br&gt;&amp;nbsp;%% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;nbsp;%% new process.
&lt;br&gt;&amp;nbsp;start(Mod, Args, Options) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;{ok, Pid} = gen:start(?MODULE, nolink, Mod, Args, [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end. 
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;gen_response(gen:start(?MODULE, nolink, Mod, Args, [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;
&lt;br&gt;&amp;nbsp;%% @spec (Name, Mod, Args, Options) -&amp;gt; wxWindow:wxWindow() 
&lt;br&gt;&amp;nbsp;%% &amp;nbsp; Name = {local, atom()}
&lt;br&gt;@@ -155,8 +154,7 @@
&lt;br&gt;&amp;nbsp;%% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;nbsp;%% new process.
&lt;br&gt;&amp;nbsp;start(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;{ok, Pid} = gen:start(?MODULE, nolink, Name, Mod, Args, [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end. 
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;gen_response(gen:start(?MODULE, nolink, Name, Mod, Args, [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% @spec (Mod, Args, Options) -&amp;gt; wxWindow:wxWindow() 
&lt;br&gt;&amp;nbsp;%% &amp;nbsp; Mod = atom() 
&lt;br&gt;@@ -166,8 +164,7 @@
&lt;br&gt;&amp;nbsp;%% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;nbsp;%% new process.
&lt;br&gt;&amp;nbsp;start_link(Mod, Args, Options) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;{ok, Pid} = gen:start(?MODULE, link, Mod, Args, [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end. 
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;gen_response(gen:start(?MODULE, link, Mod, Args, [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% @spec (Name, Mod, Args, Options) -&amp;gt; wxWindow:wxWindow() 
&lt;br&gt;&amp;nbsp;%% &amp;nbsp; Name = {local, atom()}
&lt;br&gt;@@ -177,9 +174,13 @@
&lt;br&gt;&amp;nbsp;%% &amp;nbsp; Flag = trace | log | {logfile, File} | statistics | debug
&lt;br&gt;&amp;nbsp;%% @doc Starts a generic wx_object server and invokes Mod:init(Args) in the
&lt;br&gt;&amp;nbsp;%% new process.
&lt;br&gt;-start_link(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;- &amp;nbsp; &amp;nbsp;{ok, Pid} = gen:start(?MODULE, link, Name, Mod, Args, [get(?WXE_IDENTIFIER)|Options]),
&lt;br&gt;- &amp;nbsp; &amp;nbsp;receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end. 
&lt;br&gt;+start_link(Name, Mod, Args, Options) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;gen_response(gen:start(?MODULE, link, Name, Mod, Args, [get(?WXE_IDENTIFIER)|Options])).
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;
&lt;br&gt;+gen_response({ok, Pid}) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;receive {ack, Pid, Ref = #wx_ref{}} -&amp;gt; Ref end;
&lt;br&gt;+gen_response(Reply) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;Reply.
&lt;br&gt;&amp;nbsp;
&lt;br&gt;&amp;nbsp;%% @spec(wxObject(), Request) -&amp;gt; term()
&lt;br&gt;&amp;nbsp;%% @doc Make a call to a wx_object server. 
&lt;br&gt;@@ -190,7 +191,18 @@
&lt;br&gt;&amp;nbsp;	Res
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;catch _:Reason -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;erlang:error({Reason, {?MODULE, call, [Ref, Request]}})
&lt;br&gt;- &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+%% @spec(atom(), Request) -&amp;gt; term()
&lt;br&gt;+%% @doc Make a call to a registered wx_object server
&lt;br&gt;+%% Invokes handle_call(Request, From, State) in server
&lt;br&gt;+call(Name, Request) when is_atom(Name) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;try
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok,Res} = gen:call(Name, '$gen_call', Request),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Res
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;catch _:Reason -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;erlang:error({Reason, {?MODULE, call, [Name, Request]}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;
&lt;br&gt;&amp;nbsp;%% @spec(wxObject(), Request, integer()) -&amp;gt; term()
&lt;br&gt;&amp;nbsp;%% @doc Make a call to a wx_object server. 
&lt;br&gt;&amp;nbsp;%% Invokes handle_call(Request, From, State) in server
&lt;br&gt;@@ -200,6 +212,16 @@
&lt;br&gt;&amp;nbsp;	Res
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;catch _:Reason -&amp;gt;
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;erlang:error({Reason, {?MODULE, call, [Ref, Request, Timeout]}})
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;end;
&lt;br&gt;+%% @spec(atom(), Request, integer()) -&amp;gt; term()
&lt;br&gt;+%% @doc Make a call to a registered wx_object server
&lt;br&gt;+%% Invokes handle_call(Request, From, State) in server
&lt;br&gt;+call(Name, Request, Timeout) when is_atom(Name) -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;try
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{ok,Res} = gen:call(Name, '$gen_call', Request, Timeout),
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Res
&lt;br&gt;+ &amp;nbsp; &amp;nbsp;catch _:Reason -&amp;gt;
&lt;br&gt;+ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;erlang:error({Reason, {?MODULE, call, [Name, Request, Timeout]}})
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;end.
&lt;br&gt;&amp;nbsp;	 &amp;nbsp; &amp;nbsp;
&lt;br&gt;&amp;nbsp;%% -----------------------------------------------------------------
&lt;br&gt;&lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/wx_object-fixes.-tp25819342p25819342.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25681481</id>
	<title>Re: Patch fix for c:nc R13B02-1</title>
	<published>2009-09-30T06:52:34Z</published>
	<updated>2009-09-30T06:52:34Z</updated>
	<author>
		<name>Alex Suraci</name>
	</author>
	<content type="html">Actually, that patch is wrong; fixed patch attached.
&lt;br&gt;&lt;br&gt;Tested locally this time, works perfectly.
&lt;br&gt;&lt;br&gt;&lt;br&gt;On Wed, Sep 30, 2009 at 9:06 AM, Alex Suraci &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25681481&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;i.am@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Discussion:
&lt;br&gt;&amp;gt;    &lt;a href=&quot;http://www.erlang.org/cgi-bin/ezmlm-cgi?2:mss:1525:lhkkmhkfakilgfinpgae&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/cgi-bin/ezmlm-cgi?2:mss:1525:lhkkmhkfakilgfinpgae&lt;/a&gt;&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Fixes c:nc not working when the source is compiled to an outdir or
&lt;br&gt;&amp;gt; compiled from anywhere but the cwd.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Without this patch, things like `make:all([netload])' (or even just
&lt;br&gt;&amp;gt; `nc(&amp;quot;path/to/file&amp;quot;)')
&lt;br&gt;&amp;gt; are rendered completely useless. They'll compile the file, but not load them as
&lt;br&gt;&amp;gt; c:nc is almost always looking in the wrong place for the .beam file.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; --
&lt;br&gt;&amp;gt; Alex
&lt;br&gt;&amp;gt;
&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;Alex
&lt;br&gt;&lt;br /&gt; &lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;cnc.patch&lt;/strong&gt; (888 bytes) &lt;a href=&quot;http://old.nabble.com/attachment/25681481/0/cnc.patch&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Patch-fix-for-c%3Anc-R13B02-1-tp25680711p25681481.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25680711</id>
	<title>Patch fix for c:nc R13B02-1</title>
	<published>2009-09-30T06:06:40Z</published>
	<updated>2009-09-30T06:06:40Z</updated>
	<author>
		<name>Alex Suraci</name>
	</author>
	<content type="html">Discussion:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;a href=&quot;http://www.erlang.org/cgi-bin/ezmlm-cgi?2:mss:1525:lhkkmhkfakilgfinpgae&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/cgi-bin/ezmlm-cgi?2:mss:1525:lhkkmhkfakilgfinpgae&lt;/a&gt;&lt;br&gt;&lt;br&gt;Fixes c:nc not working when the source is compiled to an outdir or
&lt;br&gt;compiled from anywhere but the cwd.
&lt;br&gt;&lt;br&gt;Without this patch, things like `make:all([netload])' (or even just
&lt;br&gt;`nc(&amp;quot;path/to/file&amp;quot;)')
&lt;br&gt;are rendered completely useless. They'll compile the file, but not load them as
&lt;br&gt;c:nc is almost always looking in the wrong place for the .beam file.
&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;Alex
&lt;br&gt;&lt;br /&gt; &lt;br /&gt;&lt;br&gt;________________________________________________________________
&lt;br&gt;erlang-patches mailing list. See &lt;a href=&quot;http://www.erlang.org/faq.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.erlang.org/faq.html&lt;/a&gt;&lt;br&gt;erlang-patches (at) erlang.org&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;cnc.patch&lt;/strong&gt; (864 bytes) &lt;a href=&quot;http://old.nabble.com/attachment/25680711/0/cnc.patch&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Patch-fix-for-c%3Anc-R13B02-1-tp25680711p25680711.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25672848</id>
	<title>Re: Re: Fixes for building erlang under windows</title>
	<published>2009-09-29T16:48:39Z</published>
	<updated>2009-09-29T16:48:39Z</updated>
	<author>
		<name>Davide Marquês</name>
	</author>
	<content type="html">Hi again,
&lt;br&gt;&lt;br&gt;With a bit of help (thanks guys!) I was able to build everything and now
&lt;br&gt;have a (hopefully) fully working erlang installation.
&lt;br&gt;All the patches and build steps are available here:
&lt;br&gt;Building erlang using Visual C++ 2008 Express
&lt;br&gt;Edition&amp;lt;&lt;a href=&quot;http://github.com/davide/erl_interface-examples/blob/master/doc/Building%20erlang%20using%20Visual%20C++%202008%20Express%20Edition.txt&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://github.com/davide/erl_interface-examples/blob/master/doc/Building%20erlang%20using%20Visual%20C++%202008%20Express%20Edition.txt&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;I'll be doing development on this new system and I'll let you know if
&lt;br&gt;anything's broken.
&lt;br&gt;&lt;br&gt;Cheers,
&lt;br&gt;:Davide
&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Fixes-for-building-erlang-under-windows-tp25611750p25672848.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25644030</id>
	<title>Re: Re: Fixes for building erlang under windows</title>
	<published>2009-09-28T04:15:04Z</published>
	<updated>2009-09-28T04:15:04Z</updated>
	<author>
		<name>Davide Marquês</name>
	</author>
	<content type="html">Hi again,
&lt;br&gt;&lt;br&gt;2009/9/28 Dan Gudmundsson &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25644030&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;dgud@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; From the README.win32
&lt;br&gt;&amp;gt; =&amp;gt; &amp;nbsp;Get and unpack wxWidgets-2.8.9 or higher to /opt/local/pgm inside
&lt;br&gt;&amp;gt; cygwin
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;br&gt;&amp;gt;
&lt;br&gt;Doh!
&lt;br&gt;Copying the files now. I'll let you know how it goes.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;gt; The configure script only looks there on windows when building with VC++
&lt;br&gt;&amp;gt; We didn't try anything fancy for the windows build there are so few
&lt;br&gt;&amp;gt; building
&lt;br&gt;&amp;gt; from the source on that platform.
&lt;br&gt;&amp;gt;
&lt;br&gt;Hope my tutorial/guide can help improve that. At least it shows that it's
&lt;br&gt;possible to build erlang with a free (as in beer) toolchain.
&lt;br&gt;&lt;br&gt;Thanks for the RTFM. :)
&lt;br&gt;:Davide
&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Fixes-for-building-erlang-under-windows-tp25611750p25644030.html" />
</entry>

</feed>
