1: %% -*- coding: utf-8 -*-
    2: %%
    3: %% %CopyrightBegin%
    4: %%
    5: %% Copyright Ericsson AB 2004-2013. All Rights Reserved.
    6: %%
    7: %% The contents of this file are subject to the Erlang Public License,
    8: %% Version 1.1, (the "License"); you may not use this file except in
    9: %% compliance with the License. You should have received a copy of the
   10: %% Erlang Public License along with this software. If not, it can be
   11: %% retrieved online at http://www.erlang.org/.
   12: %%
   13: %% Software distributed under the License is distributed on an "AS IS"
   14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   15: %% the License for the specific language governing rights and limitations
   16: %% under the License.
   17: %%
   18: %% %CopyrightEnd%
   19: %%
   20: -module(shell_SUITE).
   21: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   22: 	 init_per_group/2,end_per_group/2]).
   23: 
   24: -export([forget/1, records/1, known_bugs/1, otp_5226/1, otp_5327/1,
   25: 	 otp_5435/1, otp_5195/1, otp_5915/1, otp_5916/1,
   26: 	 bs_match_misc_SUITE/1, bs_match_int_SUITE/1,
   27: 	 bs_match_tail_SUITE/1, bs_match_bin_SUITE/1,
   28: 	 bs_construct_SUITE/1,
   29: 	 refman_bit_syntax/1, 
   30: 	 progex_bit_syntax/1, progex_records/1, 
   31: 	 progex_lc/1, progex_funs/1,
   32: 	 otp_5990/1, otp_6166/1, otp_6554/1,
   33: 	 otp_7184/1, otp_7232/1, otp_8393/1, otp_10302/1]).
   34: 
   35: -export([ start_restricted_from_shell/1, 
   36: 	  start_restricted_on_command_line/1,restricted_local/1]).
   37: 
   38: %% Internal export.
   39: -export([otp_5435_2/0, prompt1/1, prompt2/1, prompt3/1, prompt4/1,
   40: 	 prompt5/1]).
   41: 
   42: %%
   43: %% Define to run outside of test server
   44: %%
   45: %% -define(STANDALONE,1).
   46: 
   47: -ifdef(STANDALONE).
   48: -define(config(A,B),config(A,B)).
   49: -define(t,test_server).
   50: -export([config/2]).
   51: -define(line, noop, ).
   52: config(priv_dir,_) ->
   53:     ".".
   54: -else.
   55: -include_lib("test_server/include/test_server.hrl").
   56: -export([init_per_testcase/2, end_per_testcase/2]).
   57: % Default timetrap timeout (set in init_per_testcase).
   58: -define(default_timeout, ?t:minutes(2)).
   59: init_per_testcase(_Case, Config) ->
   60:     ?line Dog = ?t:timetrap(?default_timeout),
   61:     ?line OrigPath = code:get_path(),
   62:     ?line code:add_patha(?config(priv_dir,Config)),
   63:     [{orig_path,OrigPath}, {watchdog, Dog} | Config].
   64: 
   65: end_per_testcase(_Case, Config) ->
   66:     ?line Dog = ?config(watchdog, Config),
   67:     ?line test_server:timetrap_cancel(Dog),
   68:     ?line OrigPath = ?config(orig_path,Config),
   69:     ?line code:set_path(OrigPath),
   70:     ?line application:unset_env(stdlib, restricted_shell),
   71:     ?line (catch code:purge(user_default)),
   72:     ?line (catch code:delete(user_default)),
   73:     ok.
   74: -endif.
   75: 
   76: suite() -> [{ct_hooks,[ts_install_cth]}].
   77: 
   78: all() -> 
   79:     [forget, records, known_bugs, otp_5226, otp_5327,
   80:      otp_5435, otp_5195, otp_5915, otp_5916, {group, bits},
   81:      {group, refman}, {group, progex}, {group, tickets},
   82:      {group, restricted}].
   83: 
   84: groups() -> 
   85:     [{restricted, [],
   86:       [start_restricted_from_shell,
   87:        start_restricted_on_command_line, restricted_local]},
   88:      {bits, [],
   89:       [bs_match_misc_SUITE, bs_match_tail_SUITE,
   90:        bs_match_bin_SUITE, bs_construct_SUITE]},
   91:      {refman, [], [refman_bit_syntax]},
   92:      {progex, [],
   93:       [progex_bit_syntax, progex_records, progex_lc,
   94:        progex_funs]},
   95:      {tickets, [],
   96:       [otp_5990, otp_6166, otp_6554, otp_7184,
   97:        otp_7232, otp_8393, otp_10302]}].
   98: 
   99: init_per_suite(Config) ->
  100:     Config.
  101: 
  102: end_per_suite(_Config) ->
  103:     ok.
  104: 
  105: init_per_group(_GroupName, Config) ->
  106:     Config.
  107: 
  108: end_per_group(_GroupName, Config) ->
  109:     Config.
  110: 
  111: 
  112: -record(state, {bin, reply, leader, unic = latin1}).
  113: 
  114: 
  115: start_restricted_from_shell(doc) ->
  116:     ["Test that a restricted shell can be started from the normal shell"];
  117: start_restricted_from_shell(suite) ->
  118:     [];
  119: start_restricted_from_shell(Config) when is_list(Config) ->
  120:     ?line [{error,nofile}] = scan(<<"begin shell:start_restricted("
  121: 				    "nonexisting_module) end.">>),
  122:     ?line Test = filename:join(?config(priv_dir, Config), 
  123: 			       "test_restricted.erl"),
  124:     Contents = <<"-module(test_restricted).
  125:                   -export([local_allowed/3, non_local_allowed/3]).
  126:                   local_allowed(m,[],State) ->
  127:                       {true,State};
  128:                   local_allowed(ugly,[],_State) ->
  129:                       non_conforming_reply;
  130:                   local_allowed(_,_,State) ->
  131:                       {false,State}.
  132: 
  133:                   non_local_allowed({shell,stop_restricted},[],State) ->
  134:                       {true,State};
  135:                   non_local_allowed({erlang,'+'},[_],State) ->
  136:                       {true,State};
  137:                   non_local_allowed({erlang,'-'},[_,_],_State) ->
  138:                       non_conforming_reply;
  139:                   non_local_allowed({h, d}, [Arg], S) ->
  140:                       {{redirect, {erlang,hd}, [Arg]}, S};
  141:                   non_local_allowed(_,_,State) ->
  142:                       {false,State}.
  143:                  ">>,
  144:     ?line ok = compile_file(Config, Test, Contents, []),
  145:     ?line "exception exit: restricted shell starts now" = 
  146: 	comm_err(<<"begin shell:start_restricted("
  147: 			 "test_restricted) end.">>),
  148:     ?line {ok, test_restricted} = 
  149: 	application:get_env(stdlib, restricted_shell),
  150:     ?line "Module" ++ _ = t(<<"begin m() end.">>),
  151:     ?line "exception exit: restricted shell does not allow c(foo)" = 
  152: 	comm_err(<<"begin c(foo) end.">>),
  153:     ?line "exception exit: restricted shell does not allow init:stop()" = 
  154: 	comm_err(<<"begin init:stop() end.">>),
  155:     ?line "exception exit: restricted shell does not allow init:stop()" = 
  156: 	comm_err(<<"begin F = fun() -> init:stop() end, F() end.">>),
  157:     ?line "exception error: an error occurred when evaluating an arithmetic expression" =
  158: 	comm_err(<<"begin +a end.">>),
  159:     ?line "exception exit: restricted shell does not allow a + b" = 
  160: 	comm_err(<<"begin a+b end.">>),
  161:     ?line "exception exit: restricted shell does not allow - b" = 
  162: 	comm_err(<<"begin -b end.">>),
  163:     ?line "exception exit: restricted shell does not allow 1 + 2" = 
  164: 	comm_err(<<"begin if atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
  165:     ?line "exception exit: restricted shell does not allow 1 + 2" = 
  166: 	comm_err(<<"begin if is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
  167:     ?line "exception exit: restricted shell does not allow - 2" = 
  168: 	comm_err(<<"begin if - 2 -> 1; true -> 2 end end.">>),
  169:     ?line "exception exit: restricted shell does not allow - 2" = 
  170:     comm_err(<<"begin if (- 2 > 0)  andalso true -> 1; true -> 2 end end.">>),
  171:     ?line "exception exit: restricted shell does not allow - 2" = 
  172:     comm_err(<<"begin if (- 2 > 0)  orelse true -> 1; true -> 2 end end.">>),
  173:     ?line "exception exit: restricted shell does not allow 1 + 2" = 
  174:         comm_err(<<"begin if 1 + 2 > 0 -> 1; true -> 2 end end.">>),
  175:     ?line "exception exit: restricted shell does not allow 1 + 2" = 
  176:    comm_err(<<"begin if erlang:is_atom(1 + 2> 0) -> 1; true -> 2 end end.">>),
  177:     ?line "exception exit: restricted shell does not allow is_integer(1)" = 
  178:         comm_err(<<"begin if is_integer(1) -> 1; true -> 2 end end.">>),
  179:     ?line "exception exit: restricted shell does not allow is_integer(1)" = 
  180:         comm_err(<<"begin if integer(1) -> 1; true -> 2 end end.">>),
  181:     ?line "exception exit: "
  182:           "restricted shell module returned bad value non_conforming_reply" =
  183:         comm_err(<<"ugly().">>),
  184:     ?line [one] = scan(<<"h:d([one,two]).">>),
  185:     ?line "exception exit: "
  186:           "restricted shell module returned bad value non_conforming_reply" =
  187:         comm_err(<<"1 - 2.">>),
  188:     ?line "exception exit: restricted shell stopped"=  
  189: 	comm_err(<<"begin shell:stop_restricted() end.">>),
  190:     ?line undefined = 
  191: 	application:get_env(stdlib, restricted_shell),
  192:     ok.
  193: 
  194: start_restricted_on_command_line(doc) ->
  195:     ["Check restricted shell when started from the command line"];
  196: start_restricted_on_command_line(suite) ->
  197:     [];
  198: start_restricted_on_command_line(Config) when is_list(Config) ->
  199:     ?line {ok,Node} = start_node(shell_suite_helper_1,
  200: 				 "-pa "++?config(priv_dir,Config)++ 
  201: 				 " -stdlib restricted_shell foo"),
  202:     ?line "Warning! Restricted shell module foo not found: nofile"++_ = 
  203: 	t({Node, <<"begin m() end.">>}),
  204:     ?line "exception exit: restricted shell does not allow m()" =
  205: 	comm_err({Node, <<"begin m() end.">>}),
  206:     ?line [ok] = 
  207: 	(catch scan({Node, <<"begin q() end.">>})),
  208:     ?line test_server:stop_node(Node),
  209:     ?line Test = filename:join(?config(priv_dir, Config), 
  210: 			       "test_restricted2.erl"),
  211:     Contents = <<"-module(test_restricted2).
  212:                   -export([local_allowed/3, non_local_allowed/3]).
  213:                   local_allowed(m,[],State) ->
  214:                       {true,State};
  215:                   local_allowed(_,_,State) ->
  216:                       {false,State}.
  217: 
  218:                   non_local_allowed({shell,stop_restricted},[],State) ->
  219:                       {true,State};
  220:                   non_local_allowed({erlang,node},[],State) ->
  221:                       {true,State};
  222:                   non_local_allowed(_,_,State) ->
  223:                       {false,State}.
  224:                  ">>,
  225:     ?line ok = compile_file(Config, Test, Contents, []),
  226:     ?line {ok,Node2} = start_node(shell_suite_helper_2,
  227: 				 "-pa "++?config(priv_dir,Config)++ 
  228: 				 " -stdlib restricted_shell test_restricted2"),
  229:     ?line "Module" ++ _ = t({Node2,<<"begin m() end.">>}),
  230:     ?line "exception exit: restricted shell does not allow c(foo)" = 
  231: 	comm_err({Node2,<<"begin c(foo) end.">>}),
  232:     ?line "exception exit: restricted shell does not allow init:stop()" = 
  233: 	comm_err({Node2,<<"begin init:stop() end.">>}),
  234:     ?line "exception exit: restricted shell does not allow init:stop()" = 
  235: 	comm_err({Node2,<<"begin F = fun() -> init:stop() end, F() end.">>}),
  236:     ?line [Node2] = 
  237: 	scan({Node2, <<"begin erlang:node() end.">>}),
  238:     ?line [Node2] = 
  239: 	scan({Node2, <<"begin node() end.">>}),
  240:     ?line "exception exit: restricted shell stopped"=  
  241: 	comm_err({Node2,<<"begin shell:stop_restricted() end.">>}),
  242:     ?line [ok] = 
  243: 	scan({Node2, <<"begin q() end.">>}),
  244:     ?line test_server:stop_node(Node2),
  245:     ok.
  246: 
  247: restricted_local(suite) ->
  248:     [];
  249: restricted_local(doc) ->
  250:     ["Tests calling local shell functions with spectacular arguments in restricted shell"];
  251: restricted_local(Config) when is_list(Config) ->
  252:     ?line [{error,nofile}] = scan(<<"begin shell:start_restricted("
  253: 				    "nonexisting_module) end.">>),
  254:     ?line Test = filename:join(?config(priv_dir, Config), 
  255: 			       "test_restricted_local.erl"),
  256:     Contents = <<"-module(test_restricted_local).
  257:                   -export([local_allowed/3, non_local_allowed/3]).
  258:                   local_allowed(m,[],State) ->
  259:                       {true,State};
  260:                   local_allowed(banan,_,State) ->
  261:                       {true,State};
  262:                   local_allowed(funkis,_,State) ->
  263:                       {true,State};
  264:                   local_allowed(c,_,State) ->
  265:                       {true,State};
  266:                   local_allowed(_,_,State) ->
  267:                       {false,State}.
  268: 
  269:                   non_local_allowed({shell,stop_restricted},[],State) ->
  270:                       {true,State};
  271:                   non_local_allowed(_,_,State) ->
  272:                       {false,State}.
  273:                  ">>,
  274:     ?line ok = compile_file(Config, Test, Contents, []),
  275:     ?line Test2 = filename:join(?config(priv_dir, Config), 
  276: 			       "user_default.erl"),
  277:     Contents2 = <<"-module(user_default).
  278:                   -export([funkis/1,apple/1]).
  279:                   funkis(F) when is_function(F) ->
  280:                       funkis;
  281:                   funkis(_) ->
  282:                       nofunkis.
  283:                   apple(_) ->
  284:                       apple.
  285:                  ">>,
  286:     ?line ok = compile_file(Config, Test2, Contents2, []),
  287:     ?line "exception exit: restricted shell starts now" = 
  288: 	comm_err(<<"begin shell:start_restricted("
  289: 			 "test_restricted_local) end.">>),
  290:     ?line {ok, test_restricted_local} = 
  291: 	application:get_env(stdlib, restricted_shell),
  292:     ?line "exception exit: restricted shell does not allow foo(" ++ _ = 
  293: 	comm_err(<<"begin F=fun() -> hello end, foo(F) end.">>),
  294:     ?line "exception error: undefined shell command banan/1" = 
  295: 	comm_err(<<"begin F=fun() -> hello end, banan(F) end.">>),
  296:     ?line "{error,"++_ = t(<<"begin F=fun() -> hello end, c(F) end.">>),
  297:     ?line "exception exit: restricted shell does not allow l(" ++ _ = 
  298: 	comm_err(<<"begin F=fun() -> hello end, l(F) end.">>),
  299:     ?line "exception error: variable 'F' is unbound" = 
  300: 	comm_err(<<"begin F=fun() -> hello end, f(F), F end.">>),
  301:     ?line [funkis] = 
  302: 	scan(<<"begin F=fun() -> hello end, funkis(F) end.">>),
  303:     ?line "exception exit: restricted shell does not allow apple(" ++ _ =
  304: 	comm_err(<<"begin F=fun() -> hello end, apple(F) end.">>),
  305:     ?line "exception exit: restricted shell stopped"=  
  306: 	comm_err(<<"begin shell:stop_restricted() end.">>),
  307:     ?line undefined = 
  308: 	application:get_env(stdlib, restricted_shell),
  309:     ?line (catch code:purge(user_default)),
  310:     ?line true = (catch code:delete(user_default)),
  311:     ok.
  312:     
  313: 
  314: forget(doc) ->
  315:     ["f/0 and f/1"];
  316: forget(suite) ->
  317:     [];
  318: forget(Config) when is_list(Config) ->
  319:     %% f/0
  320:     ?line [ok] = scan(<<"begin f() end.">>),
  321:     ?line "1: variable 'A' is unbound" = 
  322:         comm_err(<<"A = 3, f(), A.">>),
  323:     ?line [ok] = scan(<<"A = 3, A = f(), A.">>),
  324: 
  325:     %% f/1
  326:     ?line [ok] = scan(<<"begin f(A) end.">>),
  327:     ?line "1: variable 'A' is unbound" = 
  328:         comm_err(<<"A = 3, f(A), A.">>),
  329:     ?line [ok] = scan(<<"A = 3, A = f(A), A.">>),
  330:     ?line "exception error: no function clause matching call to f/1" =
  331:         comm_err(<<"f(a).">>),
  332:     ok.
  333: 
  334: records(doc) ->
  335:     ["Test of the record support. OTP-5063."];
  336: records(suite) ->
  337:     [];
  338: records(Config) when is_list(Config) ->
  339:     %% rd/2
  340:     ?line [{attribute,_,record,{bar,_}},ok] = 
  341:         scan(<<"rd(foo,{bar}), 
  342:                 rd(bar,{foo = (#foo{})#foo.bar}),
  343:                 rl(bar).">>),
  344:     ?line "variable 'R' is unbound" = % used to work (before OTP-5878, R11B)
  345:         exit_string(<<"rd(foo,{bar}), 
  346:                        R = #foo{},
  347:                        rd(bar,{foo = R#foo.bar}).">>),
  348:     ?line "exception error: no function clause matching call to rd/2" = 
  349:         comm_err(<<"rd({foo},{bar}).">>),
  350:     ?line "bad record declaration" = exit_string(<<"A = bar, rd(foo,A).">>),
  351:     ?line [foo] = scan(<<"begin rd(foo,{bar}) end.">>),
  352:     ?line "1: record foo undefined" = 
  353:          comm_err(<<"begin rd(foo,{bar}), #foo{} end.">>),
  354:     ?line ['f o o'] = scan(<<"rd('f o o', {bar}).">>),
  355:     ?line [foo] = scan(<<"rd(foo,{bar}), rd(foo,{foo = #foo{}}).">>),
  356: 
  357:     %% rf/0,1
  358:     ?line [_, {attribute,_,record,{foo,_}},ok] = 
  359:          scan(<<"rf('_'). rd(foo,{bar}),rl().">>),
  360:     ?line "1: record foo undefined" = 
  361:         comm_err(<<"rd(foo,{bar}), #foo{}, rf(foo), #foo{}.">>),
  362:     ?line [ok,{foo,undefined}] = 
  363:         scan(<<"rd(foo,{bar}), A = #foo{}, rf(foo). A.">>),
  364:     ?line [_] = scan(<<"begin rf() end.">>),
  365:     ?line [ok] = scan(<<"begin rf(foo) end.">>),
  366: 
  367:     %% rp/1
  368:     ?line "#foo{bar = undefined}.\nok.\n" = 
  369:         t(<<"rd(foo,{bar}), rp(#foo{}).">>),
  370:     ?line [{foo,3,4,3},ok] = scan(<<"rd(foo,{a = 3, b}), rp({foo,3,4,3}).">>),
  371:     ?line "#foo{a = 12}.\nok.\n" = t(<<"rd(foo,{a = 3}), rp({foo,12}).">>),
  372:     ?line [{[{foo}],12},ok] = scan(<<"rd(foo,{a = 3}), rp({[{foo}],12}).">>),
  373: 
  374:     %% rr/1,2,3
  375:     MS = ?MODULE_STRING,
  376:     RR1 = "rr(" ++ MS ++ "). #state{}.",
  377:     ?line "[state]\n"
  378:           "#state{bin = undefined,reply = undefined,leader = undefined,\n"
  379:           "       unic = latin1}.\n" =
  380:         t(RR1),
  381:     RR2 = "rr(" ++ MS ++ ",[state]). #state{}.",
  382:     ?line "[state]\n"
  383:           "#state{bin = undefined,reply = undefined,leader = undefined,\n"
  384:           "       unic = latin1}.\n" =
  385:         t(RR2),
  386:     RR3 = "rr(" ++ MS ++ ",'_'). #state{}.",
  387:     ?line "[state]\n"
  388:           "#state{bin = undefined,reply = undefined,leader = undefined,\n"
  389:           "       unic = latin1}.\n" =
  390:         t(RR3),
  391:     RR4 = "rr(" ++ MS ++ ", '_', {d,test1}).",
  392:     ?line [[state]] = scan(RR4),
  393: 
  394:     Test = filename:join(?config(priv_dir, Config), "test.erl"),
  395:     Contents = <<"-module(test).
  396:                   -record(state, {bin, reply, leader}).
  397: 
  398:                   -ifdef(test1).
  399:                   -record(test1, {f}).
  400:                   -endif.
  401: 
  402:                   -ifdef(test2).
  403:                   -record(test2, {g}).
  404:                   -endif.">>,
  405:     ?line ok = file:write_file(Test, Contents),
  406: 
  407:     RR5 = "rr(\"" ++ Test ++ "\", '_', {d,test1}), rl([test1,test2]).",
  408:     ?line [{attribute,1,record,{test1,_}},ok] = scan(RR5),
  409:     RR6 = "rr(\"" ++ Test ++ "\", '_', {d,test2}), rl([test1,test2]).",
  410:     ?line [{attribute,1,record,{test2,_}},ok] = scan(RR6),
  411:     RR7 = "rr(\"" ++ Test ++ 
  412:            "\", '_', [{d,test1},{d,test2,17}]), rl([test1,test2]).",
  413:     ?line [{attribute,1,record,{test1,_}},{attribute,1,record,{test2,_}},
  414:            ok] = scan(RR7),
  415:     ?line PreReply = scan(<<"rr(prim_file).">>), % preloaded...
  416:     ?line true = is_list(PreReply),
  417:     ?line Dir = filename:join(?config(priv_dir, Config), "*.erl"),
  418:     ?line RR8 = "rp(rr(\"" ++ Dir ++ "\")).",
  419:     ?line [_,ok] = scan(RR8),
  420:     file:delete(Test),
  421: 
  422:     RR1000 = "begin rr(" ++ MS ++ ") end.",
  423:     ?line [_] = scan(RR1000),
  424:     RR1001 = "begin rr(" ++ MS ++ ", state) end.",
  425:     ?line [_] = scan(RR1001),
  426:     RR1002 = "begin rr(" ++ MS ++ ", state,{i,'.'}) end.",
  427:     ?line [_] = scan(RR1002),
  428: 
  429:     ?line [{error,nofile}] = scan(<<"rr(not_a_module).">>),
  430:     ?line [{error,invalid_filename}] = scan(<<"rr({foo}).">>),
  431:     ?line [[]] = scan(<<"rr(\"not_a_file\").">>),
  432: 
  433:     %% using records
  434:     ?line [2] = scan(<<"rd(foo,{bar}), record_info(size, foo).">>),
  435:     ?line [true] = scan(<<"rd(foo,{bar}), is_record(#foo{}, foo).">>),
  436:     ?line [true] = scan(<<"rd(foo,{bar}), erlang:is_record(#foo{}, foo).">>),
  437:     ?line [true] = scan(<<"rd(foo,{bar}), 
  438:                      fun() when record(#foo{},foo) -> true end().">>),
  439:     ?line [2] = scan(<<"rd(foo,{bar}), #foo.bar.">>),
  440:     ?line "#foo{bar = 17}.\n" = 
  441:         t(<<"rd(foo,{bar}), A = #foo{}, A#foo{bar = 17}.">>),
  442: 
  443:     %% test of is_record/2 in lc
  444:     ?line "[#foo{bar = 3}].\n" = 
  445:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  446:             "is_record(X, foo)].">>),
  447:     ?line "[x,[],{a,b}].\n" = 
  448:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  449:             "not is_record(X, foo)].">>),
  450:     ?line "[#foo{bar = 3}].\n" = 
  451:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  452:             "begin is_record(X, foo) end].">>),
  453:     ?line "[x,[],{a,b}].\n" = 
  454:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  455:             "begin not is_record(X, foo) end].">>),
  456: 
  457:     ?line "[#foo{bar = 3},x,[],{a,b}].\n" = 
  458:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  459:             "is_record(X, foo) or not is_binary(X)].">>),
  460:     ?line "[#foo{bar = 3},x,[],{a,b}].\n" = 
  461:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  462:             "not is_record(X, foo) or not is_binary(X)].">>),
  463:     ?line "[#foo{bar = 3}].\n" = 
  464:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  465:             "is_record(X, foo) or is_reference(X)].">>),
  466:     ?line "[x,[],{a,b}].\n" = 
  467:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  468:             "not is_record(X, foo) or is_reference(X)].">>),
  469: 
  470:     ?line "[#foo{bar = 3},x,[],{a,b}].\n" = 
  471:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  472:             "begin is_record(X, foo) or not is_binary(X) end].">>),
  473:     ?line "[#foo{bar = 3},x,[],{a,b}].\n" = 
  474:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  475:             "begin not is_record(X, foo) or not is_binary(X) end].">>),
  476:     ?line "[#foo{bar = 3}].\n" = 
  477:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  478:             "begin is_record(X, foo) or is_reference(X) end].">>),
  479:     ?line "[x,[],{a,b}].\n" = 
  480:         t(<<"rd(foo,{bar}), [X || X <- [#foo{bar=3},x,[],{a,b}],"
  481:             "begin not is_record(X, foo) or is_reference(X) end].">>),
  482: 
  483:     ?line [ok] = 
  484:         scan(<<"rd(a,{}), is_record({a},a) andalso true, b().">>),
  485:     
  486:     %% nested record defs
  487:     ?line "#b{a = #a{}}.\n" = t(<<"rd(a,{}), rd(b, {a = #a{}}), #b{}.">>),
  488: 
  489:     ?line [ok,ok,ok] = scan(<<"rf('_'), rp(rp(rl(rf(rf(rf(rl())))))).">>),
  490: 
  491:     ok.
  492: 
  493: known_bugs(doc) ->
  494:     ["Known bugs."];
  495: known_bugs(suite) ->
  496:     [];
  497: known_bugs(Config) when is_list(Config) ->
  498:     %% erl_eval:merge_bindings/2 cannot handle _removal_ of bindings.
  499:     ?line [3] = scan(<<"A = 3, length(begin f(A), [3] end), A.">>),
  500:     ok.
  501: 
  502: otp_5226(doc) ->
  503:     ["OTP-5226. Wildcards accepted when reading BEAM files using rr/1,2,3."];
  504: otp_5226(suite) ->
  505:     [];
  506: otp_5226(Config) when is_list(Config) ->
  507:     Test1 = <<"-module(test1).
  508:                -record('_test1', {a,b}).">>,
  509:     Test2 = <<"-module(test2).
  510:                -record('_test2', {c,d}).">>,
  511:     ?line File1 = filename("test1.erl", Config),
  512:     ?line File2 = filename("test2.erl", Config),
  513:     ?line Beam = filename("*.beam", Config),
  514:     ?line ok = compile_file(Config, File1, Test1, [no_debug_info]),
  515:     ?line ok = compile_file(Config, File2, Test2, [no_debug_info]),
  516:     RR = "rr(\"" ++ Beam ++ "\").",
  517:     ?line [Recs] = scan(RR),
  518:     ?line true = lists:member('_test1', Recs),
  519:     ?line true = lists:member('_test2', Recs),
  520:     file:delete(filename("test1.beam", Config)),
  521:     file:delete(filename("test2.beam", Config)),
  522:     file:delete(File1),
  523:     file:delete(File2),
  524:     ok.
  525: 
  526: otp_5327(doc) ->
  527:     ["OTP-5226. Test of eval_bits, mostly."];
  528: otp_5327(suite) ->
  529:     [];
  530: otp_5327(Config) when is_list(Config) ->
  531:     ?line "exception error: bad argument" = 
  532:         comm_err(<<"<<\"hej\":default>>.">>),
  533:     ?line <<"abc">> = 
  534:         erl_parse:normalise({bin,1,[{bin_element,1,{string,1,"abc"},
  535:                                     default,default}]}),
  536:     ?line [<<"abc">>] = scan(<<"<<(<<\"abc\">>):3/binary>>.">>),
  537:     ?line [<<"abc">>] = scan(<<"<<(<<\"abc\">>)/binary>>.">>),
  538:     ?line "exception error: bad argument" = 
  539:         comm_err(<<"<<(<<\"abc\">>):4/binary>>.">>),
  540:     ?line true = byte_size(hd(scan("<<3.14:64/float>>."))) =:= 8,
  541:     ?line true = byte_size(hd(scan("<<3.14:32/float>>."))) =:= 4,
  542:     ?line "exception error: bad argument" = 
  543:         comm_err(<<"<<3.14:128/float>>.">>),
  544:     ?line "exception error: bad argument" = 
  545:         comm_err(<<"<<10:default>>.">>),
  546:     ?line [<<98,1:1>>] = scan(<<"<<3:3,5:6>>.">>),
  547:     ?line {'EXIT',{badarg,_}} = 
  548:         (catch erl_parse:normalise({bin,1,[{bin_element,1,{integer,1,17},
  549:                                             {atom,1,all},
  550:                                             default}]})),
  551:     ?line [<<-20/signed>>] = scan(<<"<<-20/signed>> = <<-20>>.">>),
  552:     ?line [<<-300:16/signed>>] = 
  553:              scan(<<"<<-300:16/signed>> = <<-300:16>>.">>),
  554:     ?line [<<-1000:24/signed>>] = 
  555:              scan(<<"<<-1000:24/signed>> = <<-1000:24>>.">>),
  556:     ?line [<<-(1 bsl 29):32/signed>>] = 
  557:         scan(<<"<<-(1 bsl 29):32/signed>> = <<-(1 bsl 29):32>>.">>),
  558: 
  559:     ?line "exception error: no match of right hand side value <<0,0,0>>" = 
  560:         comm_err(<<"<<B:3/unit:7-binary,_/binary>> = <<0:24>>.">>),
  561:     ?line true = [<<103133:64/float>>] =:= 
  562:         scan(<<"<<103133:64/float>> = <<103133:64/float>>.">>),
  563:     ?line true = [<<103133.0:64/float>>] =:= 
  564:         scan(<<"<<103133.0:64/float>> = <<103133:64/float>>.">>),
  565:     ?line true = [<<103133:64/float>>] =:= scan(<<"<<103133:64/float>>.">>),
  566:     Int = 17,
  567:     ?line true = [<<Int:64/float>>] =:= scan(<<"Int = 17, <<Int:64/float>>.">>),
  568:     ?line "exception error: no match of right hand side value" ++ _ = 
  569:         comm_err(<<"<<103133:64/binary>> = <<103133:64/float>>.">>),
  570:     ?line "exception error: interpreted function with arity 1 called with two arguments" = 
  571:         comm_err(<<"(fun(X) -> X end)(a,b).">>),
  572:     ?line {'EXIT', {{illegal_pattern,_}, _}} =
  573:         (catch evaluate("<<A:a>> = <<17:32>>.", [])),
  574:     C = <<"
  575:          <<A:4,B:4,C:4,D:4,E:4,F:4>> = <<\"hej\">>,
  576:          case <<7:4,A:4,B:4,C:4,D:4,E:4,F:4,3:4>> of
  577:             <<_:4,\"hej\",3:4>> -> 1;
  578:             _ -> 2
  579:          end.
  580:         ">>,
  581:     ?line 1 = evaluate(C, []),
  582:     %% unbound_var would be nicer...
  583:     ?line {'EXIT',{{illegal_pattern,_},_}} = 
  584:         (catch evaluate(<<"<<A:B>> = <<17:32>>.">>, [])),
  585:     %% undefined_bittype is turned into badmatch:
  586:     ?line {'EXIT',{{badmatch,<<17:32>>},_}} = 
  587:         (catch evaluate(<<"<<A/apa>> = <<17:32>>.">>, [])),
  588:     ?line {'EXIT',_} = 
  589:         (catch evaluate(<<"<<17/binary-unit:8-unit:16>>.">>, [])),
  590:     ?line {'EXIT',_} = 
  591:         (catch evaluate(<<"<<17:32/unsigned-signed>> = <<17:32>>.">>, [])),
  592:     ?line {'EXIT',_} = 
  593:         (catch evaluate(<<"<<17:32/unsigned-signed>>.">>, [])),
  594:     ?line <<17:32>> = evaluate(<<"<<17:32/signed-signed>>.">>, []),
  595:     ?line {'EXIT',_} = 
  596:         (catch evaluate(<<"<<32/unit:8>>.">>, [])),
  597:     ok.
  598: 
  599: otp_5435(doc) ->
  600:     ["OTP-5435. sys_pre_expand not in the path."];
  601: otp_5435(suite) ->
  602:     [];
  603: otp_5435(Config) when is_list(Config) ->
  604:     ?line true = <<103133:64/float>> =:= 
  605:         evaluate(<<"<<103133:64/float>> = <<103133:64/float>>.">>, []),
  606:     ?line true = <<103133.0:64/float>> =:= 
  607:         evaluate(<<"<<103133.0:64/float>> = <<103133:64/float>>.">>, []),
  608:     ?line true = is_alive(),
  609:     ?line {ok, Node} = start_node(shell_SUITE_otp_5435),
  610:     ?line ok = rpc:call(Node, ?MODULE, otp_5435_2, []),
  611:     ?line ?t:stop_node(Node),
  612:     ok.
  613:              
  614: start_node(Name) ->
  615:     ?line PA = filename:dirname(code:which(?MODULE)),
  616:     ?t:start_node(Name, slave, [{args, "-pa " ++ PA}]).
  617: 
  618: otp_5435_2() ->
  619:     ?line true = code:del_path(compiler),
  620:     %% sys_pre_expand can no longer be found
  621:     %% OTP-5876. But erl_expand_records can!
  622:     ?line [{attribute,_,record,{bar,_}},ok] = 
  623:         scan(<<"rd(foo,{bar}), 
  624:                 rd(bar,{foo = (#foo{})#foo.bar}),
  625:                 rl(bar).">>),
  626:     ok.
  627: 
  628: otp_5195(doc) ->
  629:     ["OTP-5195. QLC, mostly."];
  630: otp_5195(suite) ->
  631:     [];
  632: otp_5195(Config) when is_list(Config) ->
  633:     %% QLC. It was easier to put these cases here than in qlc_SUITE.
  634:     ?line "[#a{b = undefined}].\n" = 
  635:         t(<<"rd(a,{b}), qlc:e(qlc:q([X || X <- [#a{}],is_record(X, a)])).">>),
  636: 
  637:     %% An experimental shell used to translate error tuples:
  638:     %% "(qlc) \"1: generated variable 'X' must not be used in "
  639:     %% "list expression\".\n" = 
  640:     %%    t(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>),
  641:     %% Same as last one (if the shell does not translate error tuples):
  642:     ?line [{error,qlc,{1,qlc,{used_generator_variable,'X'}}}] = 
  643:         scan(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>),
  644:     ?line {error,qlc,{1,qlc,{used_generator_variable,'X'}}} = 
  645:         evaluate(<<"qlc:q([X || X <- [{a}], Y <- [X]]).">>, []),
  646:     Ugly = <<"qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],ugly()])])).">>,
  647:     ?line "undefined shell command ugly/0" = error_string(Ugly),
  648:     ?line {'EXIT',{undef,_}} = (catch evaluate(Ugly, [])),
  649: 
  650:     V_1 = <<"qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],v(-1)])])).">>,
  651:     ?line "- 1: command not found" = comm_err(V_1),
  652:     ?line {'EXIT', {undef,_}} = (catch evaluate(V_1, [])),
  653: 
  654:     ?line "1\n2\n3\n3.\n" = 
  655:         t(<<"1. 2. 3. 3 = fun(A) when A =:= 2 -> v(3) end(v(2)).">>),
  656: 
  657:     ?line List4 = t(<<"[a,list]. A = [1,2]. "
  658:                       "qlc:q([X || X <- qlc:append(A, v(1))]). "
  659:                       "[1,2,a,list] = qlc:e(v(-1)).">>),
  660:     ?line "[1,2,a,list].\n" = string:substr(List4, string:len(List4)-13),
  661: 
  662:     ok.
  663: 
  664: otp_5915(doc) ->
  665:     ["OTP-5915. Strict record tests in guards."];
  666: otp_5915(suite) ->
  667:     [];
  668: otp_5915(Config) when is_list(Config) ->
  669:     C = <<"
  670:         rd(r, {a = 4,b}),
  671:         rd(r1, {a,b}),
  672:         rd(r2, {a = #r1{},b,c=length([1,2,3])}),
  673:         rd(r3, {a = fun(_) -> #r1{} end(1), b}),
  674: 
  675:         foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}),
  676:         0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}),
  677:         1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3),
  678:         2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N ->
  679:                     2 end(2),
  680:         3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}),
  681:         ok = fun() ->
  682:                      F = fun(A) when record(A#r.a, r1) -> 4;
  683:                             (A) when record(A#r1.a, r1) -> 5
  684:                          end,
  685:                      5 = F(#r1{a = #r1{}}),
  686:                      4 = F(#r{a = #r1{}}),
  687:                      ok
  688:              end(),
  689:         3 = fun(A) when record(A#r1.a, r),
  690:                               (A#r1.a)#r.a > 3 -> 3
  691:             end(#r1{a = #r{a = 4}}),
  692:         7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}),
  693:         [#r1{a = 2,b = 1}] = 
  694:             fun() ->
  695:                     [A || A <- [#r1{a = 1, b = 3}, 
  696:                                 #r2{a = 2,b = 1}, 
  697:                                 #r1{a = 2, b = 1}],
  698:                           A#r1.a > 
  699:                               A#r1.b]
  700:             end(),
  701:         {[_],b} = 
  702:             fun(L) ->
  703:                     %% A is checked only once:
  704:                     R1 = [{A,B} || A <- L, A#r1.a, B <- L, A#r1.b],
  705:                     A = #r2{a = true},
  706:                     %% A is checked again:
  707:                     B = if A#r1.a -> a; true -> b end,
  708:                     {R1,B}
  709:             end([#r1{a = true, b = true}]),
  710: 
  711:         p = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
  712:                (_) -> p
  713:             end(#r1{a = 2}),
  714: 
  715:         o = fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o;
  716:                (_) -> p
  717:             end(#r1{a = 2}),
  718: 
  719:         3 = fun(A) when A#r1.a > 3, 
  720:                         record(A, r1) -> 3
  721:             end(#r1{a = 5}),
  722: 
  723:         ok = fun() ->
  724:                      F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2;
  725:                             (A) when (A#r1.a =:= 1) orelse (A#r1.a) -> 1;
  726:                             (A) when (A#r2.a =:= 2) andalso (A#r2.b) -> 3
  727:                          end,
  728:                      1 = F(#r1{a = 1}),
  729:                      2 = F(#r2{a = true}),
  730:                      3 = F(#r2{a = 2, b = true}),
  731:                      ok
  732:              end(),
  733: 
  734:         b = fun(A) when false or not (A#r.a =:= 1) -> a;
  735:                (_) -> b
  736:             end(#r1{a = 1}),
  737:         b = fun(A) when not (A#r.a =:= 1) or false -> a;
  738:                (_) -> b
  739:             end(#r1{a = 1}),
  740: 
  741:         ok = fun() ->
  742:                      F = fun(A) when not (A#r.a =:= 1) -> yes;
  743:                             (_) -> no
  744:                          end,
  745:                      no = F(#r1{a = 2}),
  746:                      yes = F(#r{a = 2}),
  747:                      no = F(#r{a = 1}),
  748:                      ok
  749:              end(),
  750: 
  751:         a = fun(A) when record(A, r),
  752:                         A#r.a =:= 1,
  753:                         A#r.b =:= 2 ->a
  754:             end(#r{a = 1, b = 2}),
  755:         a = fun(A) when erlang:is_record(A, r),
  756:                         A#r.a =:= 1,
  757:                         A#r.b =:= 2 -> a
  758:             end(#r{a = 1, b = 2}),
  759:         a = fun(A) when is_record(A, r),
  760:                         A#r.a =:= 1,
  761:                         A#r.b =:= 2 -> a
  762:             end(#r{a = 1, b = 2}),
  763: 
  764:         nop = fun(A) when (is_record(A, r1) and (A#r1.a > 3)) or (A#r2.a < 1) ->
  765:                       japp;
  766:                  (_) ->
  767:                       nop
  768:               end(#r2{a = 0}),
  769:         nop = fun(A) when (A#r1.a > 3) or (A#r2.a < 1) -> japp;
  770:                  (_) ->
  771:                       nop
  772:               end(#r2{a = 0}),
  773: 
  774:         ok = fun() ->
  775:                      F = fun(A) when (A#r1.a =:= 2) or (A#r2.a =:= 1) -> o;
  776:                             (_) -> p
  777:                          end,
  778:                      p = F(#r2{a = 1}),
  779:                      p = F(#r1{a = 2}),
  780:                      ok
  781:              end(),
  782: 
  783:         ok = fun() ->
  784:                      F = fun(A) when fail, A#r1.a; A#r1.a -> ab;
  785:                             (_) -> bu
  786:                          end,
  787:                      ab = F(#r1{a = true}),
  788:                      bu = F(#r2{a = true}),
  789:                      ok
  790:              end(),
  791: 
  792:         both = fun(A) when A#r.a, A#r.b -> both 
  793:                end(#r{a = true, b = true}),
  794: 
  795:         ok = fun() ->
  796:                      F = fun(A, B) when ((A#r1.a) orelse (B#r2.a)) 
  797:                                         or (B#r2.b) or (A#r1.b) -> true;
  798:                             (_, _) -> false
  799:                          end,
  800:                      true = F(#r1{a = false, b = false}, #r2{a = false, b = true}),
  801:                      false = F(#r1{a = true, b = true}, #r1{a = false, b = true}),
  802:                      ok
  803:              end(),
  804: 
  805:         ok.">>,
  806:     [ok] = scan(C),
  807:     ok.
  808: 
  809: otp_5916(doc) ->
  810:     ["OTP-5916. erlang:is_record/3 allowed in guards."];
  811: otp_5916(suite) ->
  812:     [];
  813: otp_5916(Config) when is_list(Config) ->
  814:     C = <<"
  815:         rd(r1, {a,b}),
  816:         rd(r2, {a,b}),
  817: 
  818:         true = if erlang:is_record(#r1{},r1,3) -> true; true ->  false end,
  819:         false = if erlang:is_record(#r2{},r1,3) -> true; true ->  false end,
  820: 
  821:         true = if is_record(#r1{},r1,3) -> true; true ->  false end,
  822:         false = if is_record(#r2{},r1,3) -> true; true ->  false end,
  823: 
  824:         ok.">>,
  825:     [ok] = scan(C),
  826:     ok.
  827: 
  828: 
  829: bs_match_misc_SUITE(doc) ->
  830:     ["OTP-5327. Adopted from parts of emulator/test/bs_match_misc_SUITE.erl."];
  831: bs_match_misc_SUITE(suite) -> 
  832:     [];
  833: bs_match_misc_SUITE(Config) when is_list(Config) ->
  834:     C = <<"
  835:       F1 = fun() -> 3.1415 end,
  836: 
  837:       FOne = fun() -> 1.0 end,
  838: 
  839:       Fcmp = fun(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok end,
  840: 
  841:       MakeSubBin = fun(Bin0) ->
  842:           Sz = size(Bin0),
  843:           Bin1 = <<37,Bin0/binary,38,39>>,
  844:           <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1,
  845:           Bin
  846:       end,
  847: 
  848:       MatchFloat = 
  849:             fun(Bin0, Fsz, I) ->
  850:                 Bin = MakeSubBin(Bin0),
  851:                 Bsz = size(Bin) * 8,
  852:                 Tsz = Bsz - Fsz - I,
  853:                 <<_:I,F:Fsz/float,_:Tsz>> = Bin,
  854:                 F
  855:             end,
  856: 
  857:       TFloat = fun() ->
  858:           F = F1(),
  859:           G = FOne(),
  860: 
  861:           G = MatchFloat(<<63,128,0,0>>, 32, 0),
  862:           G = MatchFloat(<<63,240,0,0,0,0,0,0>>, 64, 0),
  863: 
  864:           Fcmp(F, MatchFloat(<<F:32/float>>, 32, 0)),
  865:           Fcmp(F, MatchFloat(<<F:64/float>>, 64, 0)),
  866:           Fcmp(F, MatchFloat(<<1:1,F:32/float,127:7>>, 32, 1)),
  867:           Fcmp(F, MatchFloat(<<1:1,F:64/float,127:7>>, 64, 1)),
  868:           Fcmp(F, MatchFloat(<<1:13,F:32/float,127:3>>, 32, 13)),
  869:           Fcmp(F, MatchFloat(<<1:13,F:64/float,127:3>>, 64, 13))
  870:        end,
  871:        TFloat(),
  872: 
  873:        F2 = fun() -> 2.7133 end,
  874: 
  875:        MatchFloatLittle = fun(Bin0, Fsz, I) ->
  876:            Bin = MakeSubBin(Bin0),
  877:            Bsz = size(Bin) * 8,
  878:            Tsz = Bsz - Fsz - I,
  879:            <<_:I,F:Fsz/float-little,_:Tsz>> = Bin,
  880:            F
  881:        end,
  882: 
  883:        LittleFloat = fun() ->
  884:           F = F2(),
  885:           G = FOne(),
  886: 
  887:           G = MatchFloatLittle(<<0,0,0,0,0,0,240,63>>, 64, 0),
  888:           G = MatchFloatLittle(<<0,0,128,63>>, 32, 0),
  889: 
  890:           Fcmp(F, MatchFloatLittle(<<F:32/float-little>>, 32, 0)),
  891:           Fcmp(F, MatchFloatLittle(<<F:64/float-little>>, 64, 0)),
  892:           Fcmp(F, MatchFloatLittle(<<1:1,F:32/float-little,127:7>>, 32, 1)),
  893:           Fcmp(F, MatchFloatLittle(<<1:1,F:64/float-little,127:7>>, 64, 1)),
  894:           Fcmp(F, MatchFloatLittle(<<1:13,F:32/float-little,127:3>>, 32, 13)),
  895:           Fcmp(F, MatchFloatLittle(<<1:13,F:64/float-little,127:3>>, 64, 13))
  896:        end,
  897:        LittleFloat(),
  898: 
  899:        Sean1 = fun(<<B/binary>>) when size(B) < 4 -> small;
  900:                   (<<1, _B/binary>>) -> large
  901:                end,
  902: 
  903:        Sean = fun() ->
  904:           small = Sean1(<<>>),
  905:           small = Sean1(<<1>>),
  906:           small = Sean1(<<1,2>>),
  907:           small = Sean1(<<1,2,3>>),
  908:           large = Sean1(<<1,2,3,4>>),
  909: 
  910:           small = Sean1(<<4>>),
  911:           small = Sean1(<<4,5>>),
  912:           small = Sean1(<<4,5,6>>),
  913:           {'EXIT',{function_clause,_}} = (catch Sean1(<<4,5,6,7>>))
  914:        end,
  915:        Sean(),
  916: 
  917:        NativeBig = fun() ->
  918:            <<37.33:64/native-float>> = <<37.33:64/big-float>>,
  919:            <<3974:16/native-integer>> = <<3974:16/big-integer>>
  920:        end,
  921: 
  922:        NativeLittle = fun() ->
  923:            <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
  924:            <<7974:16/native-integer>> = <<7974:16/little-integer>>
  925:        end,
  926: 
  927:        Native = fun() ->
  928:           <<3.14:64/native-float>> = <<3.14:64/native-float>>,
  929:           <<333:16/native>> = <<333:16/native>>,
  930:           <<38658345:32/native>> = <<38658345:32/native>>,
  931:           case <<1:16/native>> of
  932:               <<0,1>> -> NativeBig();
  933:               <<1,0>> -> NativeLittle()
  934:           end
  935:        end,
  936:        Native(),
  937: 
  938:        Split = fun(<<N:16,B:N/binary,T/binary>>) -> {B,T} end,
  939: 
  940:        Split2 = fun(N, <<N:16,B:N/binary,T/binary>>) -> {B,T} end,
  941: 
  942:        Split_2 = fun(<<N0:8,N:N0,B:N/binary,T/binary>>) -> {B,T} end,
  943: 
  944:        Skip = fun(<<N:8,_:N/binary,T/binary>>) -> T end,
  945: 
  946:        SizeVar = fun() -> 
  947:            {<<45>>,<<>>} = Split(<<1:16,45>>),
  948:            {<<45>>,<<46,47>>} = Split(<<1:16,45,46,47>>),
  949:            {<<45,46>>,<<47>>} = Split(<<2:16,45,46,47>>),
  950: 
  951:            {<<45,46,47>>,<<48>>} = Split_2(<<16:8,3:16,45,46,47,48>>),
  952: 
  953:            {<<45,46>>,<<47>>} = Split2(2, <<2:16,45,46,47>>),
  954:            {'EXIT',{function_clause,_}} = 
  955:                    (catch Split2(42, <<2:16,45,46,47>>)),
  956: 
  957:            <<\"cdef\">> = Skip(<<2:8,\"abcdef\">>)
  958:        end,
  959:        SizeVar(),
  960: 
  961:        Wcheck = fun(<<A>>) when A==3-> ok1;
  962:                    (<<_,_:2/binary>>) -> ok2;
  963:                    (<<_>>) -> ok3;
  964:                    (Other) -> {error,Other}
  965:                 end,
  966: 
  967:        Wiger = fun()  ->
  968:            ok1 = Wcheck(<<3>>),
  969:            ok2 = Wcheck(<<1,2,3>>),
  970:            ok3 = Wcheck(<<4>>),
  971:            {error,<<1,2,3,4>>} = Wcheck(<<1,2,3,4>>),
  972:            {error,<<>>} = Wcheck(<<>>)
  973:        end,  
  974:        Wiger(),
  975: 
  976:        ok.
  977:        ">>,
  978:     [ok] = scan(C),
  979:     ok = evaluate(C, []).
  980: 
  981: %% This one is not run during night builds since it takes several minutes.
  982: bs_match_int_SUITE(doc) ->
  983:     ["OTP-5327. Adopted from emulator/test/bs_match_int_SUITE.erl."];
  984: bs_match_int_SUITE(suite) -> 
  985:     [];
  986: bs_match_int_SUITE(Config) when is_list(Config) ->
  987:     C = <<"
  988:        FunClause = fun({'EXIT',{function_clause,_}}) -> ok end,
  989: 
  990:        Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
  991: 
  992:        GetInt1 = fun(<<I:0>>) -> I;
  993:                     (<<I:8>>) -> I;
  994:                     (<<I:16>>) -> I;
  995:                     (<<I:24>>) -> I;
  996:                     (<<I:32>>) -> I
  997:                  end,
  998: 
  999:        GetInt2 = fun(Bin0, I, F) when size(Bin0) < 4 ->
 1000:                        Bin = <<0,Bin0/binary>>,
 1001:                        I = GetInt1(Bin),
 1002:                        F(Bin, I, F);
 1003:                     (_, I, _F) -> I
 1004:                  end,
 1005: 
 1006:        GetInt = fun(Bin) ->
 1007:                    I = GetInt1(Bin),
 1008:                    GetInt2(Bin, I, GetInt2)
 1009:                 end,
 1010: 
 1011: 
 1012:        Cmp128 = fun(<<I:128>>, I) -> equal;
 1013:                    (_, _) -> not_equal
 1014:                 end,
 1015: 
 1016:        Uint2 = fun([H|T], Acc, F) -> F(T, Acc bsl 8 bor H, F);
 1017:                   ([], Acc, _F) -> Acc
 1018:                end,
 1019: 
 1020:        Uint = fun(L) -> Uint2(L, 0, Uint2) end,
 1021: 
 1022:        Integer = fun() -> 
 1023:            0 = GetInt(Mkbin([])),
 1024:            0 = GetInt(Mkbin([0])),
 1025:            42 = GetInt(Mkbin([42])),
 1026:            255 = GetInt(Mkbin([255])),
 1027:            256 = GetInt(Mkbin([1,0])),
 1028:            257 = GetInt(Mkbin([1,1])),
 1029:            258 = GetInt(Mkbin([1,2])),
 1030:            258 = GetInt(Mkbin([1,2])),
 1031:            65534 = GetInt(Mkbin([255,254])),
 1032:            16776455 = GetInt(Mkbin([255,253,7])),
 1033:            4245492555 = GetInt(Mkbin([253,13,19,75])),
 1034:            4294967294 = GetInt(Mkbin([255,255,255,254])),
 1035:            4294967295 = GetInt(Mkbin([255,255,255,255])),
 1036:            Eight = [200,1,19,128,222,42,97,111],
 1037:            Cmp128(Eight, Uint(Eight)),
 1038:            FunClause(catch GetInt(Mkbin(lists:seq(1,5))))
 1039:        end,
 1040:        Integer(),
 1041: 
 1042:        Sint = fun(Bin) ->
 1043:                   case Bin of
 1044:                       <<I:8/signed>> -> I;
 1045:                       <<I:8/signed,_:3,_:5>> -> I;
 1046:                       Other -> {no_match,Other}
 1047:                   end
 1048:               end,
 1049: 
 1050:        SignedInteger = fun() ->
 1051:            {no_match,_} = Sint(Mkbin([])),
 1052:            {no_match,_} = Sint(Mkbin([1,2,3])),
 1053:            127 = Sint(Mkbin([127])),
 1054:            -1 = Sint(Mkbin([255])),
 1055:            -128 = Sint(Mkbin([128])),
 1056:            42 = Sint(Mkbin([42,255])),
 1057:            127 = Sint(Mkbin([127,255]))
 1058:        end,
 1059:        SignedInteger(),
 1060: 
 1061:        Dynamic5 = fun(Bin, S1, S2, A, B) ->
 1062:                       case Bin of
 1063:                           <<A:S1,B:S2>> ->
 1064:                               % io:format(\"~p ~p ~p ~p~n\", [S1,S2,A,B]),
 1065:                               ok;
 1066:                           _Other -> erlang:error(badmatch, [Bin,S1,S2,A,B])
 1067:                       end
 1068:                    end,
 1069: 
 1070:        Dynamic2 = fun(Bin, S1, F) when S1 >= 0 ->
 1071:                        S2 = size(Bin) * 8 - S1,
 1072:                        Dynamic5(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1),
 1073:                        F(Bin, S1-1, F);
 1074:                      (_, _, _) -> ok
 1075:                   end,
 1076: 
 1077:        Dynamic = fun(Bin, S1) ->
 1078:           Dynamic2(Bin, S1, Dynamic2)
 1079:        end,
 1080: 
 1081:        Dynamic(Mkbin([255]), 8),
 1082:        Dynamic(Mkbin([255,255]), 16),
 1083:        Dynamic(Mkbin([255,255,255]), 24),
 1084:        Dynamic(Mkbin([255,255,255,255]), 32),
 1085:            
 1086:        BigToLittle4 = 
 1087:            fun([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc, F) when N >= 8 ->
 1088:                       F(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc], F);
 1089:               (List, N, Acc, _F) -> lists:sublist(List, 1, N) ++ Acc
 1090:            end,
 1091: 
 1092:        BigToLittle = 
 1093:             fun(List, N) -> BigToLittle4(List, N, [], BigToLittle4) end,
 1094: 
 1095:        ReversedSublist =
 1096:              fun(_List, 0, Acc, _F) -> Acc;
 1097:                 ([H|T], N, Acc, F) -> F(T, N-1, [H|Acc], F)
 1098:              end,
 1099:     
 1100:        TwoComplementAndReverse = 
 1101:              fun([H|T], Carry, Acc, F) ->
 1102:                       Sum = 1-H+Carry,
 1103:                       F(T, Sum div 2, [Sum rem 2|Acc], F);
 1104:                 ([], Carry, Acc, _F) -> [Carry|Acc]
 1105:              end,
 1106: 
 1107:        MakeInt = fun(_List, 0, Acc, _F) -> Acc;
 1108:                     ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
 1109:                  end,
 1110: 
 1111:        MakeSignedInt = 
 1112:              fun(_List, 0) -> 0;
 1113:                 ([0|_]=List, N) -> MakeInt(List, N, 0, MakeInt);
 1114:                 ([1|_]=List0, N) ->
 1115:                     List1 = ReversedSublist(List0, N, [], ReversedSublist),
 1116:                     List2 = TwoComplementAndReverse(List1, 1, [], 
 1117:                                                     TwoComplementAndReverse),
 1118:                     -MakeInt(List2, length(List2), 0, MakeInt)
 1119:              end,
 1120:     
 1121:       BitsToList =
 1122:            fun([H|T], 0, F) -> F(T, 16#80, F);
 1123:               ([H|_]=List, Mask, F) ->
 1124:                    [case H band Mask of
 1125:                        0 -> 0;
 1126:                        _ -> 1
 1127:                     end | F(List, Mask bsr 1, F)];
 1128:               ([], _, _F) -> []
 1129:            end,
 1130: 
 1131:        MoreDynamic3 = 
 1132:             fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
 1133:                 Action(Bin, List, Bef, Aft-Bef),
 1134:                 F(Action, Bin, List, Bef, Aft-1, F);
 1135:                (_, _, _, _, _, _) -> ok
 1136:             end,
 1137: 
 1138:        MoreDynamic2 = 
 1139:             fun(Action, Bin, [_|T]=List, Bef, F) ->
 1140:                    MoreDynamic3(Action, Bin, List, Bef, size(Bin)*8, 
 1141:                                 MoreDynamic3),
 1142:                    F(Action, Bin, T, Bef+1, F);
 1143:                 (_, _, [], _, _F) -> ok
 1144:             end,
 1145: 
 1146:        MoreDynamic1 = 
 1147:             fun(Action, Bin) ->
 1148:                    BitList = BitsToList(binary_to_list(Bin),16#80,BitsToList),
 1149:                    MoreDynamic2(Action, Bin, BitList, 0, MoreDynamic2)
 1150:             end,
 1151: 
 1152:        MoreDynamic = fun() ->
 1153:            % Unsigned big-endian numbers.
 1154:            Unsigned  = fun(Bin, List, SkipBef, N) ->
 1155:                                SkipAft = 8*size(Bin) - N - SkipBef,
 1156:                                <<_:SkipBef,Int:N,_:SkipAft>> = Bin,
 1157:                                Int = MakeInt(List, N, 0, MakeInt)
 1158:                        end,
 1159:            MoreDynamic1(Unsigned, erlang:md5(Mkbin([42]))),
 1160: 
 1161:            %% Signed big-endian numbers.
 1162:            Signed  = fun(Bin, List, SkipBef, N) ->
 1163:                              SkipAft = 8*size(Bin) - N - SkipBef,
 1164:                              <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin,
 1165:                              case MakeSignedInt(List, N) of
 1166:                                  Int -> ok;
 1167:                                  Other ->
 1168:                                      io:format(\"Bin = ~p,\", [Bin]),
 1169:                                      io:format(\"SkipBef = ~p, N = ~p\", 
 1170:                                                [SkipBef,N]),
 1171:                                      io:format(\"Expected ~p, got ~p\", 
 1172:                                                [Int,Other])
 1173:                              end
 1174:                      end,
 1175:            MoreDynamic1(Signed, erlang:md5(Mkbin([43]))),
 1176: 
 1177:            %% Unsigned little-endian numbers.
 1178:            UnsLittle  = fun(Bin, List, SkipBef, N) ->
 1179:                                 SkipAft = 8*size(Bin) - N - SkipBef,
 1180:                                 <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
 1181:                                 Int = MakeInt(BigToLittle(List, N), N, 0, 
 1182:                                               MakeInt)
 1183:                         end,
 1184:            MoreDynamic1(UnsLittle, erlang:md5(Mkbin([44]))),
 1185: 
 1186:            %% Signed little-endian numbers.
 1187:            SignLittle  = fun(Bin, List, SkipBef, N) ->
 1188:                                  SkipAft = 8*size(Bin) - N - SkipBef,
 1189:                                  <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin,
 1190:                                  Little = BigToLittle(List, N),
 1191:                                  Int = MakeSignedInt(Little, N)
 1192:                          end,
 1193:            MoreDynamic1(SignLittle, erlang:md5(Mkbin([45])))
 1194:        end,
 1195:        MoreDynamic(),
 1196: 
 1197:        ok.
 1198:        ">>,
 1199:     [ok] = scan(C),
 1200:     ok = evaluate(C, []).
 1201: 
 1202: bs_match_tail_SUITE(doc) ->
 1203:     ["OTP-5327. Adopted from emulator/test/bs_match_tail_SUITE.erl."];
 1204: bs_match_tail_SUITE(suite) -> 
 1205:     [];
 1206: bs_match_tail_SUITE(Config) when is_list(Config) ->
 1207:     C = <<"
 1208:           GetTailUsed = fun(<<A:1,T/binary>>) -> {A,T} end,
 1209: 
 1210:           GetTailUnused = fun(<<A:15,_/binary>>) -> A end,
 1211: 
 1212:           GetDynTailUsed = fun(Bin, Sz) ->
 1213:                               <<A:Sz,T/binary>> = Bin,
 1214:                               {A,T}
 1215:                            end,
 1216: 
 1217:           GetDynTailUnused = fun(Bin, Sz) ->
 1218:                                  <<A:Sz,_/binary>> = Bin,
 1219:                                  A
 1220:                              end,
 1221: 
 1222:           Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
 1223: 
 1224:           TestZeroTail = fun(<<A:8>>) -> A end,
 1225: 
 1226:           TestZeroTail2 = fun(<<_A:4,_B:4>>) -> ok end,
 1227: 
 1228:           ZeroTail = fun() ->
 1229:               7 = (catch TestZeroTail(Mkbin([7]))),
 1230:               {'EXIT',{function_clause,_}} = 
 1231:                    (catch TestZeroTail(Mkbin([1,2]))),
 1232:               {'EXIT',{function_clause,_}} = 
 1233:                    (catch TestZeroTail2(Mkbin([1,2,3])))
 1234:           end,
 1235:           ZeroTail(),
 1236: 
 1237:           AlGetTailUsed = fun(<<A:16,T/binary>>) -> {A,T} end,
 1238: 
 1239:           AlGetTailUnused = fun(<<A:16,_/binary>>) -> A end,
 1240: 
 1241:           Aligned = fun() ->
 1242:             Tail1 = Mkbin([]),
 1243:             {258,Tail1} = AlGetTailUsed(Mkbin([1,2])),
 1244:             Tail2 = Mkbin(lists:seq(1, 127)),
 1245:             {35091,Tail2} = AlGetTailUsed(Mkbin([137,19|Tail2])),
 1246: 
 1247:             64896 = AlGetTailUnused(Mkbin([253,128])),
 1248:             64895 = AlGetTailUnused(Mkbin([253,127|lists:seq(42, 255)])),
 1249: 
 1250:             Tail3 = Mkbin(lists:seq(0, 19)),
 1251:             {0,Tail1} = GetDynTailUsed(Tail1, 0),
 1252:             {0,Tail3} = GetDynTailUsed(Mkbin([Tail3]), 0),
 1253:             {73,Tail3} = GetDynTailUsed(Mkbin([73|Tail3]), 8),
 1254: 
 1255:             0 = GetDynTailUnused(Mkbin([]), 0),
 1256:             233 = GetDynTailUnused(Mkbin([233]), 8),
 1257:             23 = GetDynTailUnused(Mkbin([23,22,2]), 8)
 1258:           end,
 1259:           Aligned(),
 1260:     
 1261:           UnAligned = fun() ->
 1262:             {'EXIT',{function_clause,_}} = 
 1263:                    (catch GetTailUsed(Mkbin([42]))),
 1264:             {'EXIT',{{badmatch,_},_}} = 
 1265:                    (catch GetDynTailUsed(Mkbin([137]), 3)),
 1266:             {'EXIT',{function_clause,_}} = 
 1267:                    (catch GetTailUnused(Mkbin([42,33]))),
 1268:             {'EXIT',{{badmatch,_},_}} = 
 1269:                    (catch GetDynTailUnused(Mkbin([44]), 7))
 1270:           end,
 1271:           UnAligned(),
 1272:           ok.
 1273:        ">>,
 1274:     [ok] = scan(C),
 1275:     ok = evaluate(C, []).
 1276: 
 1277: bs_match_bin_SUITE(doc) ->
 1278:     ["OTP-5327. Adopted from emulator/test/bs_match_bin_SUITE.erl."];
 1279: bs_match_bin_SUITE(suite) -> 
 1280:     [];
 1281: bs_match_bin_SUITE(Config) when is_list(Config) ->
 1282:     ByteSplitBinary = 
 1283:         <<"ByteSplit = 
 1284:              fun(L, B, Pos, Fun) when Pos >= 0 ->
 1285:                      Sz1 = Pos,
 1286:                      Sz2 = size(B) - Pos,
 1287:                      <<B1:Sz1/binary,B2:Sz2/binary>> = B,
 1288:                      B1 = list_to_binary(lists:sublist(L, 1, Pos)),
 1289:                      B2 = list_to_binary(lists:nthtail(Pos, L)),
 1290:                         Fun(L, B, Pos-1, Fun);
 1291:                  (L, B, _, _Fun) -> ok
 1292:              end,
 1293:            Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
 1294:            L = lists:seq(0, 57),
 1295:            B = Mkbin(L),
 1296:            ByteSplit(L, B, size(B), ByteSplit),
 1297:            Id = fun(I) -> I end,
 1298:            MakeUnalignedSubBinary =
 1299:              fun(Bin0) ->
 1300:                      Bin1 = <<0:3,Bin0/binary,31:5>>,
 1301:                      Sz = size(Bin0),
 1302:                      <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
 1303:                      Bin
 1304:              end,
 1305:            Unaligned = MakeUnalignedSubBinary(B),
 1306:            ByteSplit(L, Unaligned, size(Unaligned), ByteSplit),
 1307:            ok.
 1308:         ">>,
 1309:     [ok] = scan(ByteSplitBinary),
 1310:     ok = evaluate(ByteSplitBinary, []),
 1311:     BitSplitBinary = 
 1312:         <<"Mkbin = fun(L) when list(L) -> list_to_binary(L) end,
 1313: 
 1314:            MakeInt = 
 1315:               fun(List, 0, Acc, _F) -> Acc;
 1316:                  ([H|T], N, Acc, F) -> F(T, N-1, Acc bsl 1 bor H, F)
 1317:               end,
 1318: 
 1319:            MakeBinFromList = 
 1320:                fun(List, 0, _F) -> Mkbin([]);
 1321:                   (List, N, F) ->
 1322:                     list_to_binary([MakeInt(List, 8, 0, MakeInt),
 1323: 		                    F(lists:nthtail(8, List), N-8, F)])
 1324:                end,
 1325: 
 1326:            BitSplitBinary3 = 
 1327:                 fun(Action, Bin, List, Bef, Aft, F) when Bef =< Aft ->
 1328:                     Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
 1329:                     F(Action, Bin, List, Bef, Aft-8, F);
 1330:                    (_, _, _, _, _, _) -> ok 
 1331:                 end,
 1332: 
 1333:            BitSplitBinary2 = 
 1334:                 fun(Action, Bin, [_|T]=List, Bef, F) ->
 1335:                        BitSplitBinary3(Action, Bin, List, Bef, size(Bin)*8, 
 1336:                                        BitSplitBinary3),
 1337:                        F(Action, Bin, T, Bef+1, F);
 1338:                    (Action, Bin, [], Bef, F) -> ok
 1339:                 end,
 1340: 
 1341:            BitsToList =
 1342:                 fun([H|T], 0, F) -> F(T, 16#80, F);
 1343:                    ([H|_]=List, Mask, F) ->
 1344:                         [case H band Mask of
 1345:                             0 -> 0;
 1346:                             _ -> 1
 1347:                          end | F(List, Mask bsr 1, F)];
 1348:                    ([], _, _F) -> []
 1349:                 end,
 1350: 
 1351:            BitSplitBinary1 = 
 1352:                  fun(Action, Bin) ->
 1353:                     BitList = BitsToList(binary_to_list(Bin), 16#80, 
 1354:                                          BitsToList),
 1355:                     BitSplitBinary2(Action, Bin, BitList, 0, BitSplitBinary2)
 1356:                  end,
 1357: 
 1358:            Fun = fun(Bin, List, SkipBef, N) ->
 1359:                   SkipAft = 8*size(Bin) - N - SkipBef,
 1360:                   <<I1:SkipBef,OutBin:N/binary-unit:1,I2:SkipAft>> = Bin,
 1361:                   OutBin = MakeBinFromList(List, N, MakeBinFromList)
 1362:            end,
 1363: 
 1364:            BitSplitBinary1(Fun, erlang:md5(<<1,2,3>>)),
 1365:            Id = fun(I) -> I end,
 1366:            MakeUnalignedSubBinary =
 1367:              fun(Bin0) ->
 1368:                      Bin1 = <<0:3,Bin0/binary,31:5>>,
 1369:                      Sz = size(Bin0),
 1370:                      <<0:3,Bin:Sz/binary,31:5>> = Id(Bin1),
 1371:                      Bin
 1372:              end,
 1373:            BitSplitBinary1(Fun, MakeUnalignedSubBinary(erlang:md5(<<1,2,3>>))),
 1374:            ok.
 1375:         ">>,
 1376:     [ok] = scan(BitSplitBinary),
 1377:     ok = evaluate(BitSplitBinary, []).
 1378: 
 1379: -define(FAIL(Expr), "{'EXIT',{badarg,_}} = (catch " ??Expr ")").
 1380: 
 1381: -define(COF(Int0),
 1382:         "(fun(Int) ->
 1383:                        true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
 1384:                        true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
 1385:                    end)(Nonliteral(" ??Int0 ")),
 1386:         true = <<" ??Int0 ":32/float>> =:= <<(float("??Int0")):32/float>>,
 1387:         true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
 1388: 
 1389: -define(COF64(Int0),
 1390:         "(fun(Int) ->
 1391:                        true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
 1392:                    end)(Nonliteral(" ??Int0 ")),
 1393:         true = <<" ??Int0 ":64/float>> =:= <<(float("??Int0")):64/float>>").
 1394: 
 1395: bs_construct_SUITE(doc) ->
 1396:     ["OTP-5327. Adopted from parts of emulator/test/bs_construct_SUITE.erl."];
 1397: bs_construct_SUITE(suite) -> 
 1398:     [];
 1399: bs_construct_SUITE(Config) when is_list(Config) ->
 1400:     C1 = <<"
 1401: 
 1402:        Testf_1 = fun(W, B) -> "
 1403:             ?FAIL(<<42:W>>) ","
 1404:             ?FAIL(<<3.14:W/float>>) ","
 1405:             ?FAIL(<<B:W/binary>>) "
 1406:        end,
 1407: 
 1408:        TestF = fun() -> "
 1409:             ?FAIL(<<3.14>>) ","
 1410:             ?FAIL(<<<<1,2>>>>) ","
 1411: 
 1412:             ?FAIL(<<2.71/binary>>) ","
 1413:             ?FAIL(<<24334/binary>>) ","
 1414:             ?FAIL(<<24334344294788947129487129487219847/binary>>) ","
 1415: 
 1416:             ?FAIL(<<<<1,2,3>>/float>>) ",
 1417: 
 1418:             %% Negative field widths.
 1419:             Testf_1(-8, <<1,2,3,4,5>>),"
 1420: 
 1421:             ?FAIL(<<42:(-16)>>) ","
 1422:             ?FAIL(<<3.14:(-8)/float>>) ","
 1423:             ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>) ","
 1424:             ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>) ","
 1425:             ?FAIL(<<<<23,56,0,2>>:(anka)>>) "
 1426:        end,                 
 1427:        TestF(),
 1428: 
 1429:        NotUsed1 = fun(I, BinString) -> <<I:32,BinString/binary>>, ok end,
 1430: 
 1431:        NotUsed2 = fun(I, Sz) -> <<I:Sz>>, ok end,
 1432: 
 1433:        NotUsed3 = fun(I) -><<I:(-8)>>, ok end,
 1434: 
 1435:        NotUsed = fun() ->
 1436:             ok = NotUsed1(3, <<\"dum\">>),
 1437:             {'EXIT',{badarg,_}} = (catch NotUsed1(3, \"dum\")), "
 1438:             ?FAIL(NotUsed2(444, -2)) ","
 1439:             ?FAIL(NotUsed2(444, anka)) ","
 1440:             ?FAIL(NotUsed3(444)) "
 1441:        end,
 1442:        NotUsed(),            
 1443: 
 1444:        InGuard3 = fun(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
 1445:                      (Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
 1446:                      (Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
 1447:                      (Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> 
 1448:                           cant_happen;
 1449:                      (_, _, _) -> nope
 1450:                   end,
 1451: 
 1452:        InGuard = fun() ->
 1453:             1 = InGuard3(<<16#74ad:16>>, 16#e95, 5),
 1454:             2 = InGuard3(<<16#3A,16#F7,\"hello\">>, 16#3AF7, <<\"hello\">>),
 1455:             3 = InGuard3(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
 1456:             nope = InGuard3(<<1>>, 42, b),
 1457:             nope = InGuard3(<<1>>, a, b),
 1458:             nope = InGuard3(<<1,2>>, 1, 1),
 1459:             nope = InGuard3(<<4,5>>, 1, 2.71),
 1460:             nope = InGuard3(<<4,5>>, 1, <<12,13>>)
 1461:        end,
 1462:        InGuard(),
 1463: 
 1464:        Nonliteral = fun(X) -> X end,
 1465: 
 1466:        CoerceToFloat = fun() -> "
 1467:            ?COF(0) ","
 1468:            ?COF(-1) ","
 1469:            ?COF(1) ","
 1470:            ?COF(42) ","
 1471:            ?COF(255) ","
 1472:            ?COF(-255) ","
 1473:            ?COF64(298748888888888888888888888883478264866528467367364766666666666666663) ","
 1474:            ?COF64(-367546729879999999999947826486652846736736476555566666663) "
 1475:        end,
 1476:        CoerceToFloat(),
 1477:        ok.
 1478:        ">>,
 1479:     [ok] = scan(C1),
 1480:     ok = evaluate(C1, []),
 1481: 
 1482:     %% There is another one, lib/compiler/test/bs_construct_SUITE.erl...
 1483:     C2 = <<"
 1484:        I = fun(X) -> X end,
 1485: 
 1486:        Fail = fun() -> 
 1487: 
 1488:          I_minus_777 = I(-777),
 1489:          I_minus_2047 = I(-2047),
 1490: 
 1491:          %% One negative field size, but the sum of field sizes will be 1 byte.
 1492:          %% Make sure that we reject that properly.
 1493: 
 1494:          {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
 1495:                                              57:I_minus_2047/unit:8>>),
 1496: 
 1497:          %% Same thing, but use literals.
 1498:          {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8,
 1499:                                              57:(-2047)/unit:8>>),
 1500: 
 1501:          %% Bad alignment.
 1502:          I_one = I(1),
 1503:          <<1:1>> = <<2375:I_one>>,
 1504:          <<3:2>> = <<45:1,2375:I_one>>,
 1505:          <<14:4>> = <<45:1,2375:I_one,918:2>>,
 1506:          <<118:7>> = <<45:1,2375:I_one,918:5>>,
 1507: 
 1508:          %% Not numbers.
 1509:          {'EXIT',{badarg,_}} = (catch <<45:(I(not_a_number))>>),
 1510:          {'EXIT',{badarg,_}} = (catch <<13:8,45:(I(not_a_number))>>),
 1511: 
 1512:          %% Unaligned sizes.
 1513:          BadSz = I(7),
 1514:          <<2:4>> = <<34:4>>,
 1515:          <<34:7>> = <<34:BadSz>>,
 1516: 
 1517:          [] = [X || {X} <- [], X == <<3:BadSz>>],
 1518:          [] = [X || {X} <- [], X == <<3:4>>]
 1519:        end,
 1520:        Fail(),
 1521: 
 1522:        FloatBin1 = fun(F) ->
 1523:          {<<1,2,3>>,F+3.0}
 1524:        end,
 1525: 
 1526:        FloatBin = fun() ->
 1527:            %% Some more coverage.
 1528:            {<<1,2,3>>,7.0} = FloatBin1(4)
 1529:        end,
 1530:        FloatBin(),
 1531: 
 1532:        ok.
 1533:        ">>,
 1534:     [ok] = scan(C2),
 1535:     ok = evaluate(C2, []).
 1536: 
 1537: evaluate(B, Vars) when is_binary(B) ->
 1538:     evaluate(binary_to_list(B), Vars);
 1539: evaluate(Str, Vars) ->
 1540:     {ok,Tokens,_} =
 1541: 	erl_scan:string(Str),
 1542:     {ok, Exprs} = erl_parse:parse_exprs(Tokens),
 1543:     case erl_eval:exprs(Exprs, Vars, none) of
 1544: 	{value, Result, _} ->
 1545: 	    Result
 1546:     end.
 1547: 
 1548: 
 1549: refman_bit_syntax(doc) ->
 1550:     ["Bit syntax examples from the Reference Manual. OTP-5237."];
 1551: refman_bit_syntax(suite) ->
 1552:     [];
 1553: refman_bit_syntax(Config) when is_list(Config) ->
 1554:     %% Reference Manual "Bit Syntax Expressions"
 1555:     ?line Bin1 = <<1,17,42>>,
 1556:     ?line true = [1,17,42] =:= binary_to_list(Bin1),
 1557:     ?line Bin2 = <<"abc">>,
 1558:     ?line true = "abc" =:= binary_to_list(Bin2),
 1559:     ?line Bin3 = <<1,17,42:16>>,
 1560:     ?line true = [1,17,0,42] =:= binary_to_list(Bin3),
 1561:     ?line <<_A,_B,C:16>> = <<1,17,42:16>>,
 1562:     ?line true = C =:= 42,
 1563:     ?line <<D:16,_E,F>> = <<1,17,42:16>>,
 1564:     ?line true = D =:= 273,
 1565:     ?line true = F =:= 42,
 1566:     <<_G,H/binary>> = <<1,17,42:16>>,
 1567:     ?line true = H =:= <<17,0,42>>,
 1568: 
 1569:     ?line [ok] = 
 1570:         scan(<<"Bin1 = <<1,17,42>>,
 1571:                          true = [1,17,42] =:= binary_to_list(Bin1),
 1572:               Bin2 = <<\"abc\">>,
 1573:                          true = \"abc\" =:= binary_to_list(Bin2),
 1574:                          Bin3 = <<1,17,42:16>>,
 1575:                       true = 
 1576:                       [1,17,0,42] =:= binary_to_list(Bin3),
 1577:                       <<A,B,C:16>> = <<1,17,42:16>>,
 1578:                       true = C =:= 42,
 1579:                       <<D:16,E,F>> = <<1,17,42:16>>,
 1580:                       true = D =:= 273,
 1581:                       true = F =:= 42,
 1582:                       <<G,H/binary>> = <<1,17,42:16>>,
 1583:                       true = H =:= <<17,0,42>>,
 1584:                       ok.">>),
 1585: 
 1586:     %% Binary comprehensions.
 1587:     ?line <<2,4,6>> =  << << (X*2) >> || <<X>> <= << 1,2,3 >> >>,
 1588:     ok.
 1589: 
 1590: 
 1591: -define(IP_VERSION, 4).
 1592: -define(IP_MIN_HDR_LEN, 5).
 1593: progex_bit_syntax(doc) ->
 1594:     ["Bit syntax examples from Programming Examples. OTP-5237."];
 1595: progex_bit_syntax(suite) ->
 1596:     [];
 1597: progex_bit_syntax(Config) when is_list(Config) ->
 1598:     Bin11 = <<1, 17, 42>>,
 1599:     true = [1, 17, 42] =:= binary_to_list(Bin11),
 1600:     Bin12 = <<"abc">>,
 1601:     true = [97, 98, 99] =:= binary_to_list(Bin12),
 1602:     
 1603:     A = 1, B = 17, C = 42,
 1604:     Bin2 = <<A, B, C:16>>,
 1605:     true = [1, 17, 00, 42] =:= binary_to_list(Bin2),
 1606:     <<D:16, E, F/binary>> = Bin2,
 1607:     true = D =:= 273,
 1608:     true = E =:= 00,
 1609:     true = [42] =:= binary_to_list(F),
 1610: 
 1611:     Fun4 = fun(Dgram) ->
 1612:                    DgramSize = byte_size(Dgram),
 1613:                    case Dgram of 
 1614:                        <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16, 
 1615:                         ID:16, Flgs:3, FragOff:13,
 1616:                         TTL:8, Proto:8, HdrChkSum:16,
 1617:                         SrcIP:32, DestIP:32, 
 1618:                         RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
 1619:                            OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
 1620:                            <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
 1621:                            {SrvcType, TotLen, Flgs, FragOff, ID, HdrChkSum,
 1622:                             Proto, TTL, SrcIP, DestIP, Data, Opts};
 1623:                        _ ->
 1624:                            not_ok
 1625:                    end
 1626:            end,
 1627:     true = Fun4(<<>>) =:= not_ok,
 1628:     true = is_tuple(Fun4(list_to_binary([<<?IP_VERSION:4,5:4>>,
 1629:                                          list_to_binary(lists:seq(1,255))]))),
 1630: 
 1631:     X = 23432324, Y = 24324234,
 1632:     <<10:7>> = <<X:1, Y:6>>,
 1633:     Z = 234324324,
 1634:     XYZ = <<X:1, Y:6, Z:1>>,
 1635:     true = [20] =:= binary_to_list(XYZ),
 1636:     Hello1 = <<"hello">>,
 1637:     Hello2 = <<$h,$e,$l,$l,$o>>,
 1638:     true = "hello" =:= binary_to_list(Hello1),
 1639:     true = "hello" =:= binary_to_list(Hello2),
 1640: 
 1641:     FunM1 = fun(<<X1:7/binary, Y1:1/binary>>) -> {X1,Y1} end,
 1642:     true = {<<"1234567">>,<<"8">>} =:= FunM1(<<"12345678">>),
 1643: 
 1644:     FunM2 = fun(<<_X1:7/binary-unit:7, _Y1:1/binary-unit:1>>) -> ok;
 1645:                (_) -> not_ok end,
 1646:     true = not_ok =:= FunM2(<<"1">>),
 1647: 
 1648:     BL = [{3,4,5},{6,7,8}],
 1649:     Lst = [0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,8],
 1650:     B1 = triples_to_bin1(BL),
 1651:     true = Lst =:= binary_to_list(B1),
 1652:     B2 = triples_to_bin2(BL),
 1653:     true = Lst =:= binary_to_list(B2),
 1654: 
 1655:     ?line [ok] = scan(
 1656:      <<"Bin11 = <<1, 17, 42>>,
 1657:         true = [1, 17, 42] =:= binary_to_list(Bin11),
 1658:         Bin12 = <<\"abc\">>,
 1659:         true = [97, 98, 99] =:= binary_to_list(Bin12),
 1660: 
 1661:         A = 1, B = 17, C = 42,
 1662:         Bin2 = <<A, B, C:16>>,
 1663:         true = [1, 17, 00, 42] =:= binary_to_list(Bin2),
 1664:         <<D:16, E, F/binary>> = Bin2,
 1665:         true = D =:= 273,
 1666:         true = E =:= 00,
 1667:         true = [42] =:= binary_to_list(F),
 1668: 
 1669:         Fun4 = fun(Dgram) ->
 1670:                        DgramSize = byte_size(Dgram),
 1671:                        case Dgram of 
 1672:                            <<4:4, HLen:4, SrvcType:8, TotLen:16, 
 1673:                             ID:16, Flgs:3, FragOff:13,
 1674:                             TTL:8, Proto:8, HdrChkSum:16,
 1675:                             SrcIP:32, DestIP:32, 
 1676:                             RestDgram/binary>> when HLen>=5, 
 1677:                                                     4*HLen=<DgramSize ->
 1678:                               OptsLen = 4*(HLen - 5),
 1679:                               <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
 1680:                               {SrvcType, TotLen, Flgs, FragOff, ID, HdrChkSum,
 1681:                                Proto, TTL, SrcIP, DestIP, Data, Opts};
 1682:                            _ ->
 1683:                               not_ok
 1684:                        end
 1685:                end,
 1686:         true = Fun4(<<>>) =:= not_ok,
 1687:         true = is_tuple(Fun4(list_to_binary
 1688:                   ([<<4:4,5:4>>,list_to_binary(lists:seq(1,255))]))),
 1689: 
 1690:         X = 23432324, Y = 24324234,
 1691:         <<10:7>> = <<X:1, Y:6>>,
 1692:         Z = 234324324,
 1693:         XYZ = <<X:1, Y:6, Z:1>>,
 1694:         true = [20] =:= binary_to_list(XYZ),
 1695:         Hello1 = <<\"hello\">>,
 1696:         Hello2 = <<$h,$e,$l,$l,$o>>,
 1697:         true = \"hello\" =:= binary_to_list(Hello1),
 1698:         true = \"hello\" =:= binary_to_list(Hello2),
 1699: 
 1700:         FunM1 = fun(<<X1:7/binary, Y1:1/binary>>) -> {X1,Y1} end,
 1701:         true = {<<\"1234567\">>,<<\"8\">>} =:= FunM1(<<\"12345678\">>),
 1702: 
 1703:         FunM2 = fun(<<_X1:7/binary-unit:7, _Y1:1/binary-unit:1>>) -> ok;
 1704:                    (_) -> not_ok end,
 1705:         true = not_ok =:= FunM2(<<\"1\">>),
 1706:         ok.">>),
 1707: 
 1708:     ok.
 1709: 
 1710: triples_to_bin1(T) ->
 1711:     triples_to_bin1(T, <<>>).
 1712: 
 1713: triples_to_bin1([{X,Y,Z} | T], Acc) ->
 1714:     triples_to_bin1(T, <<Acc/binary, X:32, Y:32, Z:32>>);   % inefficient
 1715: triples_to_bin1([], Acc) -> 
 1716:     Acc.
 1717: 
 1718: triples_to_bin2(T) ->
 1719:     triples_to_bin2(T, []).
 1720: 
 1721: triples_to_bin2([{X,Y,Z} | T], Acc) ->
 1722:     triples_to_bin2(T, [<<X:32, Y:32, Z:32>> | Acc]);
 1723: triples_to_bin2([], Acc) -> 
 1724:     list_to_binary(lists:reverse(Acc)).
 1725: 
 1726: progex_records(doc) ->
 1727:     ["Record examples from Programming Examples. OTP-5237."];
 1728: progex_records(suite) ->
 1729:     [];
 1730: progex_records(Config) when is_list(Config) ->
 1731:     Test1 = 
 1732:        <<"-module(recs).
 1733:           -record(person, {name = \"\", phone = [], address}).
 1734:           -record(name, {first = \"Robert\", last = \"Ericsson\"}).
 1735:           -record(person2, {name = #name{}, phone}).
 1736:           -export([t/0]).
 1737: 
 1738:           t() ->
 1739:               _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
 1740:               \"Robert\" = _P1#person.name,
 1741:               [0,8,2,3,4,3,1,2] = _P1#person.phone,
 1742:                undefined = _P1#person.address,
 1743: 
 1744:               _P2 = #person{name = \"Jakob\", _ = '_'},
 1745:                \"Jakob\" = _P2#person.name,
 1746:               '_' = _P2#person.phone,
 1747:               '_' = _P2#person.address,
 1748:     
 1749:               P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
 1750:               \"Joe\" = P#person.name,
 1751:               [0,8,2,3,4,3,1,2] = P#person.phone,
 1752:               undefined = P#person.address,
 1753: 
 1754:               P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
 1755:               P2 = P1#person{name=\"Robert\"},
 1756:               \"Robert\" = P2#person.name,
 1757:               [1,2,3] = P2#person.phone,
 1758:               \"A street\" = P2#person.address,
 1759:               a_person = foo(P1),
 1760: 
 1761:               {found, [1,2,3]} = 
 1762:                      find_phone([#person{name = a}, 
 1763:                                  #person{name = b, phone = [3,2,1]},
 1764:                                  #person{name = c, phone = [1,2,3]}],
 1765:                                 c),
 1766: 
 1767:               P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
 1768:               #person{name = Name} = P3, 
 1769:               \"Joe\" = Name,
 1770: 
 1771:               \"Robert\" = demo(),
 1772:               ok.
 1773: 
 1774:               foo(P) when is_record(P, person) -> a_person;
 1775:               foo(_) -> not_a_person.
 1776: 
 1777:               find_phone([#person{name=Name, phone=Phone} | _], Name) ->
 1778:                   {found,  Phone};
 1779:               find_phone([_| T], Name) ->
 1780:                   find_phone(T, Name);
 1781:               find_phone([], _Name) ->
 1782:                   not_found.
 1783: 
 1784:               demo() ->
 1785:                   P = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
 1786:                                phone=123},
 1787:                   _First = (P#person2.name)#name.first.
 1788:          ">>,
 1789:     ?line ok = run_file(Config, recs, Test1), 
 1790: 
 1791:     Test1_shell = 
 1792:        <<"rd(person, {name = \"\", phone = [], address}),
 1793:           rd(name, {first = \"Robert\", last = \"Ericsson\"}),
 1794:           rd(person2, {name = #name{}, phone}),
 1795: 
 1796:           _P1 = #person{phone=[0,8,2,3,4,3,1,2], name=\"Robert\"},
 1797:           \"Robert\" = _P1#person.name,
 1798:           [0,8,2,3,4,3,1,2] = _P1#person.phone,
 1799:            undefined = _P1#person.address,
 1800: 
 1801:           _P2 = #person{name = \"Jakob\", _ = '_'},
 1802:            \"Jakob\" = _P2#person.name,
 1803:           '_' = _P2#person.phone,
 1804:           '_' = _P2#person.address,
 1805: 
 1806:           P = #person{name = \"Joe\", phone = [0,8,2,3,4,3,1,2]},
 1807:           \"Joe\" = P#person.name,
 1808:           [0,8,2,3,4,3,1,2] = P#person.phone,
 1809:           undefined = P#person.address,
 1810: 
 1811:           P1 = #person{name=\"Joe\", phone=[1,2,3], address=\"A street\"},
 1812:           P2 = P1#person{name=\"Robert\"},
 1813:           \"Robert\" = P2#person.name,
 1814:           [1,2,3] = P2#person.phone,
 1815:           \"A street\" = P2#person.address,
 1816:           Foo = fun(P) when is_record(P, person) -> a_person;
 1817:                    (_) -> not_a_person
 1818:                 end,
 1819:           a_person = Foo(P1),
 1820: 
 1821:           Find = fun([#person{name=Name, phone=Phone} | _], Name, Fn) ->
 1822:                          {found,  Phone};
 1823:                     ([_| T], Name, Fn) ->
 1824:                          Fn(T, Name, Fn);
 1825:                     ([], _Name, _Fn) ->
 1826:                          not_found
 1827:                  end,
 1828: 
 1829:           {found, [1,2,3]} = Find([#person{name = a}, 
 1830:                                    #person{name = b, phone = [3,2,1]},
 1831:                                    #person{name = c, phone = [1,2,3]}],
 1832:                                   c, 
 1833:                                   Find),
 1834: 
 1835:           P3 = #person{name=\"Joe\", phone=[0,0,7], address=\"A street\"},
 1836:           #person{name = Name} = P3, 
 1837:           \"Joe\" = Name,
 1838: 
 1839:           Demo = fun() ->
 1840:               P17 = #person2{name= #name{first=\"Robert\",last=\"Virding\"},
 1841:                            phone=123},
 1842:               _First = (P17#person2.name)#name.first
 1843:                  end,
 1844: 
 1845:           \"Robert\" = Demo(),
 1846:           ok.
 1847:      ">>,
 1848:     ?line [ok] = scan(Test1_shell),
 1849: 
 1850:     Test2 = 
 1851:        <<"-module(recs).
 1852:           -record(person, {name, age, phone = [], dict = []}).
 1853:           -compile(export_all).
 1854: 
 1855:           t() -> ok.
 1856: 
 1857:           make_hacker_without_phone(Name, Age) ->
 1858:              #person{name = Name, age = Age, 
 1859:                       dict = [{computer_knowledge, excellent}, 
 1860:                               {drinks, coke}]}.
 1861:           print(#person{name = Name, age = Age,
 1862:                         phone = Phone, dict = Dict}) ->
 1863:               io:format(\"Name: ~s, Age: ~w, Phone: ~w ~n\" 
 1864:                         \"Dictionary: ~w.~n\", [Name, Age, Phone, Dict]).
 1865: 
 1866:           birthday(P) when record(P, person) -> 
 1867:              P#person{age = P#person.age + 1}.
 1868: 
 1869:           register_two_hackers() ->
 1870:              Hacker1 = make_hacker_without_phone(\"Joe\", 29),
 1871:              OldHacker = birthday(Hacker1),
 1872:              % The central_register_server should have 
 1873:              % an interface function for this.
 1874:              central_register_server ! {register_person, Hacker1},
 1875:              central_register_server ! {register_person, 
 1876:                        OldHacker#person{name = \"Robert\", 
 1877:                                         phone = [0,8,3,2,4,5,3,1]}}.
 1878:        ">>,
 1879:     ?line ok = run_file(Config, recs, Test2),
 1880:     ok.
 1881: 
 1882: progex_lc(doc) ->
 1883:     ["List comprehension examples from Programming Examples. OTP-5237."];
 1884: progex_lc(suite) ->
 1885:     [];
 1886: progex_lc(Config) when is_list(Config) ->
 1887:     Test1 = 
 1888:        <<"-module(lc).
 1889:           -export([t/0]).
 1890: 
 1891:           t() ->
 1892:               [a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
 1893:               [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
 1894:               [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = 
 1895:                   [{X, Y} || X <- [1,2,3], Y <- [a,b]],
 1896: 
 1897:               [1,2,3,4,5,6,7,8] = sort([4,5,1,8,3,6,7,2]),
 1898:               [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] = 
 1899:                   perms([b,u,g]),
 1900:               [] = pyth(11),
 1901:               [{3,4,5},{4,3,5}] = pyth(12),
 1902:               [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
 1903:                {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
 1904:                {16,12,20}] = pyth(50),
 1905:               [] = pyth1(11),
 1906:               [{3,4,5},{4,3,5}] = pyth1(12),
 1907:               [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
 1908:                {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
 1909:                {16,12,20}] = pyth1(50),
 1910:               [1,2,3,4,5] = append([[1,2,3],[4,5]]),
 1911:               [2,3,4] = map(fun(X) -> X + 1 end, [1,2,3]),
 1912:               [2,4] = filter(fun(X) -> X > 1 end, [0,2,4]),
 1913:               [1,2,3,7] = select(b,[{a,1},{b,2},{c,3},{b,7}]),
 1914:               [2,7] = select2(b,[{a,1},{b,2},{c,3},{b,7}]),
 1915:               ok.
 1916: 
 1917:           sort([Pivot|T]) ->
 1918:               sort([ X || X <- T, X < Pivot]) ++
 1919:               [Pivot] ++
 1920:               sort([ X || X <- T, X >= Pivot]);
 1921:           sort([]) -> [].
 1922: 
 1923:           perms([]) -> [[]];
 1924:           perms(L)  -> [[H|T] || H <- L, T <- perms(L--[H])].
 1925: 
 1926:           pyth(N) ->
 1927:               [ {A,B,C} ||
 1928:                   A <- lists:seq(1,N),
 1929:                   B <- lists:seq(1,N),
 1930:                   C <- lists:seq(1,N),
 1931:                   A+B+C =< N,
 1932:                   A*A+B*B == C*C 
 1933:               ].
 1934: 
 1935:           pyth1(N) ->
 1936:               [{A,B,C} ||
 1937:                   A <- lists:seq(1,N),
 1938:                   B <- lists:seq(1,N-A+1),
 1939:                   C <- lists:seq(1,N-A-B+2),
 1940:                   A+B+C =< N,
 1941:                   A*A+B*B == C*C ].
 1942: 
 1943:          append(L)   ->  [X || L1 <- L, X <- L1].
 1944:          map(Fun, L) -> [Fun(X) || X <- L].
 1945:          filter(Pred, L) -> [X || X <- L, Pred(X)].
 1946: 
 1947:          select(X, L) ->  [Y || {X, Y} <- L].
 1948:          select2(X, L) ->  [Y || {X1, Y} <- L, X == X1].
 1949:        ">>,
 1950:     ?line ok = run_file(Config, lc, Test1),
 1951: 
 1952:     Test1_shell = 
 1953:        <<"[a,4,b,5,6] = [X || X <- [1,2,a,3,4,b,5,6], X > 3],
 1954:           [4,5,6] = [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3],
 1955:           [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}] = 
 1956:               [{X, Y} || X <- [1,2,3], Y <- [a,b]],
 1957: 
 1958:           Sort = fun([Pivot|T], Fn) ->
 1959:                         Fn([ X || X <- T, X < Pivot], Fn) ++
 1960:                         [Pivot] ++
 1961:                         Fn([ X || X <- T, X >= Pivot], Fn);
 1962:                      ([], _Fn) -> []
 1963:                  end,
 1964: 
 1965:           [1,2,3,4,5,6,7,8] = Sort([4,5,1,8,3,6,7,2], Sort),
 1966:           Perms = fun([], _Fn) -> [[]];
 1967:                      (L, Fn)  -> [[H|T] || H <- L, T <- Fn(L--[H], Fn)]
 1968:                   end,
 1969:           [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]] = 
 1970:               Perms([b,u,g], Perms),
 1971: 
 1972:           Pyth = fun(N) ->
 1973:                       [ {A,B,C} ||
 1974:                           A <- lists:seq(1,N),
 1975:                           B <- lists:seq(1,N),
 1976:                           C <- lists:seq(1,N),
 1977:                           A+B+C =< N,
 1978:                           A*A+B*B == C*C 
 1979:                       ]
 1980:                  end,
 1981: 
 1982:           [] = Pyth(11),
 1983:           [{3,4,5},{4,3,5}] = Pyth(12),
 1984:           %[{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
 1985:           % {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
 1986:           % {16,12,20}] = Pyth(50),
 1987: 
 1988:           Pyth1 = fun(N) ->
 1989:                       [{A,B,C} ||
 1990:                           A <- lists:seq(1,N),
 1991:                           B <- lists:seq(1,N-A+1),
 1992:                           C <- lists:seq(1,N-A-B+2),
 1993:                           A+B+C =< N,
 1994:                           A*A+B*B == C*C ]
 1995:                   end,
 1996: 
 1997:           [] = Pyth1(11),
 1998:           [{3,4,5},{4,3,5}] = Pyth1(12),
 1999:           [{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{8,15,17},
 2000:            {9,12,15},{12,5,13},{12,9,15},{12,16,20},{15,8,17},
 2001:            {16,12,20}] = Pyth1(50),
 2002: 
 2003:           Append = fun(L)   ->  [X || L1 <- L, X <- L1] end,
 2004:           [1,2,3,4,5] = Append([[1,2,3],[4,5]]),
 2005:           Map = fun(Fun, L) -> [Fun(X) || X <- L] end,
 2006:           [2,3,4] = Map(fun(X) -> X + 1 end, [1,2,3]),
 2007:           Filter = fun(Pred, L) -> [X || X <- L, Pred(X)] end,
 2008:           [2,4] = Filter(fun(X) -> X > 1 end, [0,2,4]),
 2009: 
 2010:           Select = fun(X, L) ->  [Y || {X, Y} <- L] end,
 2011:           [1,2,3,7] = Select(b,[{a,1},{b,2},{c,3},{b,7}]),
 2012:           Select2 = fun(X, L) ->  [Y || {X1, Y} <- L, X == X1] end,
 2013:           [2,7] = Select2(b,[{a,1},{b,2},{c,3},{b,7}]),
 2014:           ok.
 2015:        ">>,
 2016:     ?line [ok] = scan(Test1_shell),
 2017:     ok.
 2018: 
 2019: progex_funs(doc) ->
 2020:     ["Funs examples from Programming Examples. OTP-5237."];
 2021: progex_funs(suite) ->
 2022:     [];
 2023: progex_funs(Config) when is_list(Config) ->
 2024:     Test1 = 
 2025:        <<"-module(funs).
 2026:           -compile(export_all).
 2027: 
 2028:           double([H|T]) -> [2*H|double(T)];
 2029:           double([])    -> [].
 2030: 
 2031:           add_one([H|T]) -> [H+1|add_one(T)];
 2032:           add_one([])    -> [].
 2033: 
 2034:           map(F, [H|T]) -> [F(H)|map(F, T)];
 2035:           map(F, [])    -> [].
 2036: 
 2037:           double2(L)  -> map(fun(X) -> 2*X end, L).
 2038:           add_one2(L) -> map(fun(X) -> 1 + X end, L).
 2039: 
 2040:           print_list(Stream, [H|T]) ->
 2041:               io:format(Stream, \"~p~n\", [H]),
 2042:               print_list(Stream, T);
 2043:           print_list(Stream, []) ->
 2044:               true.
 2045: 
 2046:           broadcast(Msg, [Pid|Pids]) ->
 2047:               Pid ! Msg,
 2048:               broadcast(Msg, Pids);
 2049:           broadcast(_, []) ->
 2050:               true.
 2051: 
 2052:           foreach(F, [H|T]) ->
 2053:               F(H),
 2054:               foreach(F, T);
 2055:           foreach(F, []) ->
 2056:               ok.
 2057: 
 2058:           print_list2(S, L) -> 
 2059:               foreach(fun(H) -> io:format(S, \"~p~n\",[H]) end, L).
 2060: 
 2061:           broadcast2(M, L) -> foreach(fun(Pid) -> Pid ! M end, L).
 2062: 
 2063:           t1() -> map(fun(X) -> 2 * X end, [1,2,3,4,5]).
 2064: 
 2065:           t2() -> map(fun double/1, [1,2,3,4,5]).
 2066: 
 2067:           t3() -> map({?MODULE, double3}, [1,2,3,4,5]).
 2068: 
 2069:           double3(X) -> X * 2.
 2070: 
 2071:           f(F, Args) when function(F) ->
 2072:              apply(F, Args);
 2073:           f(N, _) when integer(N) ->
 2074:              N.
 2075: 
 2076:           print_list3(File, List) ->
 2077:               {ok, Stream} = file:open(File, write),
 2078:               foreach(fun(X) -> io:format(Stream,\"~p~n\",[X]) end, List),
 2079:               file:close(Stream).
 2080: 
 2081:           print_list4(File, List) ->
 2082:               {ok, Stream} = file:open(File, write),
 2083:               foreach(fun(File) -> 
 2084:                           io:format(Stream,\"~p~n\",[File]) 
 2085:                       end, List),
 2086:               file:close(Stream).
 2087: 
 2088:           any(Pred, [H|T]) ->
 2089:               case Pred(H) of
 2090:                   true  ->  true;
 2091:                   false ->  any(Pred, T)
 2092:               end;
 2093:           any(Pred, []) ->
 2094:               false.
 2095: 
 2096:           all(Pred, [H|T]) ->
 2097:               case Pred(H) of
 2098:                   true  ->  all(Pred, T);
 2099:                   false ->  false
 2100:               end;
 2101:           all(Pred, []) ->
 2102:               true.
 2103: 
 2104:           foldl(F, Accu, [Hd|Tail]) ->
 2105:               foldl(F, F(Hd, Accu), Tail);
 2106:           foldl(F, Accu, []) -> Accu.
 2107: 
 2108:           mapfoldl(F, Accu0, [Hd|Tail]) ->
 2109:               {R,Accu1} = F(Hd, Accu0),
 2110:               {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
 2111:               {[R|Rs], Accu2};
 2112:           mapfoldl(F, Accu, []) -> {[], Accu}.
 2113: 
 2114:           filter(F, [H|T]) ->
 2115:               case F(H) of
 2116:                   true  -> [H|filter(F, T)];
 2117:                   false -> filter(F, T)
 2118:               end;
 2119:           filter(F, []) -> [].
 2120: 
 2121:           diff(L1, L2) -> 
 2122:               filter(fun(X) -> not lists:member(X, L2) end, L1).
 2123: 
 2124:           intersection(L1,L2) -> filter(fun(X) -> lists:member(X,L1) end, L2).
 2125: 
 2126:           takewhile(Pred, [H|T]) ->
 2127:               case Pred(H) of
 2128:                   true  -> [H|takewhile(Pred, T)];
 2129:                   false -> []
 2130:               end;
 2131:           takewhile(Pred, []) ->
 2132:               [].
 2133: 
 2134:           dropwhile(Pred, [H|T]) ->
 2135:               case Pred(H) of
 2136:                   true  -> dropwhile(Pred, T);
 2137:                   false -> [H|T]
 2138:               end;
 2139:           dropwhile(Pred, []) ->
 2140:               [].
 2141: 
 2142:           splitlist(Pred, L) ->
 2143:               splitlist(Pred, L, []).
 2144: 
 2145:           splitlist(Pred, [H|T], L) ->
 2146:               case Pred(H) of 
 2147:                   true  -> splitlist(Pred, T, [H|L]);
 2148:                   false -> {lists:reverse(L), [H|T]}
 2149:               end;
 2150:           splitlist(Pred, [], L) ->
 2151:               {lists:reverse(L), []}.
 2152: 
 2153:           first(Pred, [H|T]) ->
 2154:               case Pred(H) of
 2155:                   true ->
 2156:                       {true, H};
 2157:                   false ->
 2158:                       first(Pred, T)
 2159:               end;
 2160:           first(Pred, []) ->
 2161:               false.
 2162: 
 2163:           ints_from(N) ->
 2164:               fun() ->
 2165:                       [N|ints_from(N+1)]
 2166:               end.
 2167: 
 2168:           pconst(X) ->
 2169:               fun (T) ->
 2170:                  case T of
 2171:                      [X|T1] -> {ok, {const, X}, T1};
 2172:                      _      -> fail
 2173:                  end
 2174:               end.
 2175: 
 2176:           pand(P1, P2) ->
 2177:               fun (T) ->
 2178:                   case P1(T) of
 2179:                       {ok, R1, T1} ->
 2180:                           case P2(T1) of
 2181:                               {ok, R2, T2} ->
 2182:                                   {ok, {'and', R1, R2}};
 2183:                               fail ->
 2184:                                   fail
 2185:                           end;
 2186:                       fail ->
 2187:                           fail
 2188:                   end
 2189:               end.
 2190: 
 2191:           por(P1, P2) ->
 2192:               fun (T) ->
 2193:                   case P1(T) of
 2194:                       {ok, R, T1} -> 
 2195:                           {ok, {'or',1,R}, T1};
 2196:                       fail -> 
 2197:                           case P2(T) of
 2198:                               {ok, R1, T1} ->
 2199:                                   {ok, {'or',2,R1}, T1};
 2200:                               fail ->
 2201:                                   fail
 2202:                           end
 2203:                   end
 2204:               end.
 2205: 
 2206:           grammar() ->
 2207:               pand(
 2208:                    por(pconst(a), pconst(b)),
 2209:                    por(pconst(c), pconst(d))).
 2210: 
 2211:           parse(List) ->
 2212:               (grammar())(List).
 2213: 
 2214: 
 2215:           t() ->
 2216:                [2,4,6,8] = double([1,2,3,4]),
 2217:                [2,3,4,5] = add_one([1,2,3,4]),
 2218:                [2,4,6,8] = double2([1,2,3,4]),
 2219:                [2,3,4,5] = add_one2([1,2,3,4]),
 2220:                XX = ints_from(1),
 2221:                [1 | _] = XX(),
 2222:                1 = hd(XX()),
 2223:                Y = tl(XX()),
 2224:                2 = hd(Y()),
 2225: 
 2226:                P1 = pconst(a),
 2227:                {ok,{const,a},[b,c]} = P1([a,b,c]),
 2228:                fail = P1([x,y,z]),
 2229: 
 2230:                {ok,{'and',{'or',1,{const,a}},{'or',1,{const,c}}}} =
 2231:                     parse([a,c]),
 2232:                {ok,{'and',{'or',1,{const,a}},{'or',2,{const,d}}}} =
 2233:                    parse([a,d]),
 2234:                {ok,{'and',{'or',2,{const,b}},{'or',1,{const,c}}}} =
 2235:                    parse([b,c]),
 2236:                {ok,{'and',{'or',2,{const,b}},{'or',2,{const,d}}}} =
 2237:                    parse([b,d]),
 2238:                fail = parse([a,b]),
 2239:                ok.
 2240:          ">>,
 2241:     ?line ok = run_file(Config, funs, Test1),
 2242: 
 2243:     Test2_shell = 
 2244:        <<"Double = fun(X) -> 2 * X end,
 2245:           [2,4,6,8,10] = lists:map(Double, [1,2,3,4,5]),
 2246:           
 2247:           Big =  fun(X) -> if X > 10 -> true; true -> false end end,
 2248:           false = lists:any(Big, [1,2,3,4]),
 2249:           true = lists:any(Big, [1,2,3,12,5]),
 2250:           false = lists:all(Big, [1,2,3,4,12,6]),
 2251:           true = lists:all(Big, [12,13,14,15]),
 2252:           L = [\"I\",\"like\",\"Erlang\"],
 2253:           11 = lists:foldl(fun(X, Sum) -> length(X) + Sum end, 0, L),
 2254:           Upcase =  fun(X) when $a =< X,  X =< $z -> X + $A - $a;
 2255:                        (X) -> X
 2256:                     end,
 2257:           Upcase_word = fun(X) -> lists:map(Upcase, X) end,
 2258:           \"ERLANG\" = Upcase_word(\"Erlang\"),
 2259:           [\"I\",\"LIKE\",\"ERLANG\"] = lists:map(Upcase_word, L),
 2260:           {[\"I\",\"LIKE\",\"ERLANG\"],11} =
 2261:                lists:mapfoldl(fun(Word, Sum) -> 
 2262:                                   {Upcase_word(Word), Sum + length(Word)}
 2263:                               end, 0, L),
 2264:           [500,12,45] = lists:filter(Big, [500,12,2,45,6,7]),
 2265:           [200,500,45] = lists:takewhile(Big, [200,500,45,5,3,45,6]),
 2266:           [5,3,45,6] = lists:dropwhile(Big, [200,500,45,5,3,45,6]),
 2267:           {[200,500,45],[5,3,45,6]} = 
 2268:                lists:splitwith(Big, [200,500,45,5,3,45,6]),
 2269:           %% {true,45} = lists:first(Big, [1,2,45,6,123]),
 2270:           %% false = lists:first(Big, [1,2,4,5]),
 2271:           
 2272:           Adder = fun(X) -> fun(Y) -> X + Y end end,
 2273:           Add6 = Adder(6),
 2274:           16 = Add6(10),
 2275:           ok.
 2276:        ">>,
 2277:     ?line [ok] = scan(Test2_shell),
 2278:     ok.
 2279: 
 2280: 
 2281: otp_5990(doc) ->
 2282:     "OTP-5990. {erlang,is_record}.";
 2283: otp_5990(suite) -> [];
 2284: otp_5990(Config) when is_list(Config) ->
 2285:     ?line [true] = 
 2286:         scan(<<"rd('OrdSet', {orddata = {},ordtype = type}), "
 2287:                "S = #'OrdSet'{ordtype = {}}, "
 2288:                "if tuple(S#'OrdSet'.ordtype) -> true; true -> false end.">>),
 2289:     ok.
 2290: 
 2291: otp_6166(doc) ->
 2292:     "OTP-6166. Order of record definitions.";
 2293: otp_6166(suite) -> [];
 2294: otp_6166(Config) when is_list(Config) ->
 2295:     Test1 = filename:join(?config(priv_dir, Config), "test1.hrl"),
 2296:     Contents1 = <<"-module(test1).
 2297:                    -record(r5, {f}). -record(r3, {f = #r5{}}). "
 2298:                   "-record(r1, {f = #r3{}}). -record(r4, {f = #r1{}}). "
 2299:                   "-record(r2, {f = #r4{}}).">>,
 2300:     ?line ok = file:write_file(Test1, Contents1),
 2301: 
 2302:     Test2 = filename:join(?config(priv_dir, Config), "test2.hrl"),
 2303:     Contents2 = <<"-module(test2).
 2304:                    -record(r5, {f}). -record(r3, {f = #r5{}}). "
 2305:                   "-record(r1, {f = #r3{}}). -record(r4, {f = #r1{}}). "
 2306:                   "-record(r2, {f = #r4{}}).
 2307:                    -record(r6, {f = #r5{}}).            % r6 > r0
 2308:                    -record(r0, {f = #r5{}, g = #r5{}}). % r0 < r5">>,
 2309:     ?line ok = file:write_file(Test2, Contents2),
 2310:     
 2311:     RR12 = "[r1,r2,r3,r4,r5] = rr(\"" ++ Test1 ++ "\"), 
 2312:             [r0,r1,r2,r3,r4,r5,r6] = rr(\"" ++ Test2 ++ "\"), 
 2313:             R0 = #r0{}, R6 = #r6{}, 
 2314:             true = is_record(R0, r0),
 2315:             true = is_record(R6, r6),
 2316:             ok. ",
 2317:     ?line [ok] = scan(RR12),
 2318: 
 2319:     file:delete(Test1),
 2320:     file:delete(Test2),
 2321:     ok.
 2322: 
 2323: otp_6554(doc) ->
 2324:     "OTP-6554. Formatted exits and error messages.";
 2325: otp_6554(suite) -> [];
 2326: otp_6554(Config) when is_list(Config) ->
 2327:     %% Should check the stacktrace as well...
 2328:     ?line "exception error: bad argument" = 
 2329:         comm_err(<<"math:sqrt(a).">>),
 2330:     ?line "exception error: bad argument" = 
 2331:         comm_err(<<"fun(X, Y) -> X ++ Y end(a, b).">>),
 2332:     ?line "exception error: bad argument" = 
 2333:         comm_err(<<"math:sqrt(lists:seq(1,40)).">>),
 2334:     ?line "exception error: bad argument" = 
 2335:         comm_err(<<"math:sqrt(lists:seq(1,10)).">>),
 2336:     ?line "exception error: bad argument" = 
 2337:         comm_err(<<"a ++ b.">>),
 2338:     ?line "exception error: bad argument" = 
 2339:         comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
 2340:                          undefined,undefined,undefined,undefined,undefined,
 2341:                          undefined,undefined,undefined,undefined},
 2342:                     aa ++ I.">>),
 2343:     ?line "exception error: bad argument" = 
 2344:         comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
 2345:                          undefined,undefined,undefined,undefined,undefined,
 2346:                          undefined,undefined,undefined,undefined},
 2347:                     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ++ I.">>),
 2348:     ?line "exception error: bad argument" = 
 2349:         comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
 2350:                          undefined,undefined,undefined,undefined,undefined,
 2351:                          undefined,undefined,undefined,undefined},
 2352:                     I ++ I.">>),
 2353:     ?line "exception error: bad argument" = 
 2354:         comm_err(<<"fun(X) -> not X end(a).">>),
 2355:     ?line "exception error: bad argument: a" = 
 2356:         comm_err(<<"fun(A, B) -> A orelse B end(a, b).">>),
 2357:     ?line "exception error: an error occurred when evaluating an arithmetic expression" =
 2358:         comm_err(<<"math:sqrt(2)/round(math:sqrt(0)).">>),
 2359:     ?line "exception error: interpreted function with arity 1 called with no arguments" = 
 2360:         comm_err(<<"fun(V) -> V end().">>),
 2361:     ?line "exception error: interpreted function with arity 1 called with two arguments" = 
 2362:         comm_err(<<"fun(V) -> V end(1,2).">>),
 2363:     ?line "exception error: interpreted function with arity 0 called with one argument" = 
 2364:         comm_err(<<"fun() -> v end(1).">>),
 2365:     ?line "exception error: interpreted function with arity 0 called with 4 arguments" = 
 2366:         comm_err(<<"fun() -> v end(1,2,3,4).">>),
 2367:     ?line "exception error: math:sqrt/1 called with two arguments" = 
 2368:         comm_err(<<"fun math:sqrt/1(1,2).">>),
 2369:     ?line "exception error: bad function 1." ++ _ = 
 2370:         comm_err(<<"(math:sqrt(2))().">>),
 2371:     ?line "exception error: bad function [1," ++ _ = 
 2372:         comm_err(<<"(lists:seq(1, 100))().">>),
 2373:     ?line "exception error: no match of right hand side value 1" ++ _ = 
 2374:         comm_err(<<"a = math:sqrt(2).">>),
 2375:     ?line "exception error: no match of right hand side value" ++ _ = 
 2376:         comm_err(<<"I = {file_info,undefined,undefined,undefined,undefined,
 2377:                          undefined,undefined,undefined,undefined,undefined,
 2378:                          undefined,undefined,undefined,undefined},
 2379:                     a = I.">>),
 2380:     ?line "exception error: no case clause matching 1" ++ _ = 
 2381:         comm_err(<<"case math:sqrt(2) of a -> ok end.">>),
 2382:     ?line "exception error: no case clause matching [1," ++ _ = 
 2383:         comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>),
 2384:     ?line "exception error: no function clause matching" = 
 2385:         comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>),
 2386:     case test_server:is_native(erl_eval) of
 2387: 	true ->
 2388: 	    %% Native code has different exit reason. Don't bother
 2389: 	    %% testing them.
 2390: 	    ok;
 2391: 	false ->
 2392: 	    "exception error: {function_clause," =
 2393: 		comm_err(<<"erlang:error(function_clause, "
 2394: 			  "[unproper | list]).">>),
 2395: 	    %% Cheating:
 2396: 	    "exception error: no function clause matching "
 2397: 		"erl_eval:do_apply(4)" ++ _ =
 2398: 		comm_err(<<"erlang:error(function_clause, [4]).">>),
 2399: 		"exception error: no function clause matching "
 2400: 		"lists:reverse(" ++ _ =
 2401: 		comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
 2402: 		"exception error: no function clause matching "
 2403: 		"lists:reverse(34) (lists.erl, line " ++ _ =
 2404: 		comm_err(<<"lists:reverse(34).">>)
 2405:     end,
 2406:     ?line "exception error: function_clause" =
 2407:         comm_err(<<"erlang:error(function_clause, 4).">>),
 2408:     ?line "exception error: no function clause matching" ++ _ = 
 2409:         comm_err(<<"fun(a, b, c, d) -> foo end"
 2410:                    "       (lists:seq(1,17),"
 2411:                    "        lists:seq(1, 18),"
 2412:                    "        lists:seq(1, 40),"
 2413:                    "        lists:seq(1, 5)).">>),
 2414: 
 2415:     ?line "exception error: no function clause matching" = 
 2416:         comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>),
 2417:     ?line "exception error: no true branch found when evaluating an if expression" = 
 2418:         comm_err(<<"if length([a,b]) > 17 -> a end.">>),
 2419:     ?line "exception error: no such process or port" = 
 2420:         comm_err(<<"Pid = spawn(fun() -> a end),"
 2421:                    "timer:sleep(1),"
 2422:                    "link(Pid).">>),
 2423:     ?line "exception error: a system limit has been reached" = 
 2424:         comm_err(<<"list_to_atom(lists:duplicate(300,$a)).">>),
 2425:     ?line "exception error: bad receive timeout value" = 
 2426:         comm_err(<<"receive after a -> foo end.">>),
 2427:     ?line "exception error: no try clause matching 1" ++ _ = 
 2428:         comm_err(<<"try math:sqrt(2) of bar -> yes after 3 end.">>),
 2429:     ?line "exception error: no try clause matching [1" ++ _ = 
 2430:         comm_err(<<"V = lists:seq(1, 20),"
 2431:                    "try V of bar -> yes after 3 end.">>),
 2432:     ?line "exception error: undefined function math:sqrt/2" = 
 2433:         comm_err(<<"math:sqrt(2, 2).">>),
 2434:     ?line "exception error: limit of number of arguments to interpreted function "
 2435:           "exceeded" = 
 2436:         comm_err(<<"fun(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) ->"
 2437:                    "   a end().">>),
 2438:     ?line "exception error: bad filter a" = 
 2439:         comm_err(<<"[b || begin a end].">>),
 2440:     ?line "exception error: bad generator a" = 
 2441:         comm_err(<<"[X || X <- a].">>),
 2442:     ?line "exception throw: undef" = comm_err(<<"throw(undef).">>),
 2443:     ?line "exception exit: undef" = comm_err(<<"exit(undef).">>),
 2444: 
 2445:     ?line "exception exit: foo" = 
 2446:           comm_err(<<"catch spawn_link(fun() ->"
 2447:                      "                     timer:sleep(300), exit(foo) "
 2448:                      "                 end),"
 2449:                      "timer:sleep(500).">>),
 2450:     ?line [ok] = scan(
 2451:                    <<"begin process_flag(trap_exit, true),"
 2452:                      "  Pid = spawn_link(fun() ->"
 2453:                      "                       timer:sleep(300), exit(foo) "
 2454:                      "                   end),"
 2455:                      "  timer:sleep(500),"
 2456:                      "  receive {'EXIT', Pid, foo} -> ok end end.">>),
 2457:     ?line "exception exit: badarith" = 
 2458:           comm_err(<<"catch spawn_link(fun() ->"
 2459:                      "                     timer:sleep(300), 1/0 "
 2460:                      "                 end),"
 2461:                      "timer:sleep(500).">>),
 2462:     ?line "exception exit: {nocatch,foo}" = 
 2463:           comm_err(<<"catch spawn_link(fun() ->"
 2464:                      "                     timer:sleep(300), throw(foo) "
 2465:                      "                 end),"
 2466:                      "timer:sleep(500).">>),
 2467:     ?line [ok] = scan(
 2468:                    <<"begin process_flag(trap_exit, true),"
 2469:                      "  Pid = spawn_link(fun() ->"
 2470:                      "                       timer:sleep(300), throw(foo) "
 2471:                      "                   end),"
 2472:                      "  timer:sleep(500),"
 2473:                      "  receive {'EXIT', Pid, {{nocatch,foo},_}} -> ok end "
 2474:                      "end.">>),
 2475: 
 2476:     ?line "exception error: an error occurred when evaluating an arithmetic expression" =
 2477:         comm_err(<<"begin catch_exception(true), 1/0 end.">>),
 2478:     ?line "exception error: an error occurred when evaluating an arithmetic expression" =
 2479:         comm_err(<<"begin catch_exception(false), 1/0 end.">>),
 2480:     ?line "exception error: no function clause matching call to catch_exception/1" = 
 2481:         comm_err(<<"catch_exception(1).">>),
 2482: 
 2483:     %% A bug was corrected (expansion of 'try'):
 2484:     ?line "2: command not found" = 
 2485:         comm_err(<<"try 1 of 1 -> v(2) after 3 end.">>),
 2486:     %% Cover a few lines:
 2487:     ?line "3: command not found" = 
 2488:         comm_err(<<"receive foo -> foo after 0 -> v(3) end.">>),
 2489:     ?line "3: command not found" = 
 2490:         comm_err(<<"receive foo -> foo after 0 -> e(3) end.">>),
 2491:     ?line "1 / 0: command not found" = comm_err(<<"v(1/0).">>),
 2492:     ?line "1\n1.\n" = t(<<"1. e(1).">>),
 2493:     ?line [ok] = scan(<<"h().">>),
 2494:     ?line "exception exit: normal" = comm_err(<<"exit(normal).">>),
 2495:     ?line [foo] = scan(<<"begin history(0), foo end.">>),
 2496:     ?line application:unset_env(stdlib, shell_history_length),
 2497:     ?line [true] = scan(<<"begin <<10:(1024*1024*10)>>,"
 2498:                           "<<10:(1024*1024*10)>>, garbage_collect() end.">>),
 2499:     ?line "1: syntax error before: '.'" = comm_err("1-."),
 2500:     %% ?line comm_err(<<"exit().">>), % would hang
 2501:     ?line "exception error: no function clause matching call to history/1" =
 2502:         comm_err(<<"history(foo).">>),
 2503:     ?line "exception error: no function clause matching call to results/1" =
 2504:         comm_err(<<"results(foo).">>),
 2505: 
 2506:     ?line Test = filename:join(?config(priv_dir, Config), 
 2507: 			       "otp_6554.erl"),
 2508:     Contents = <<"-module(otp_6554).
 2509:                   -export([local_allowed/3, non_local_allowed/3]).
 2510:                   local_allowed(_,_,State) ->
 2511:                       {true,State}.
 2512: 
 2513:                   non_local_allowed(_,_,State) ->
 2514:                       {true,State}.
 2515:                  ">>,
 2516:     ?line ok = compile_file(Config, Test, Contents, []),
 2517:     ?line "exception exit: restricted shell starts now" = 
 2518: 	comm_err(<<"begin shell:start_restricted(otp_6554) end.">>),
 2519:     ?line "-record(r,{}).\n1.\nok.\n" = 
 2520:                     t(<<"f(), f(B), h(), b(), history(20), results(20),"
 2521:                         "rd(r, {}), rl(r), rf('_'), rl(), rf(),"
 2522:                         "rp(1), _ = rr({foo}), _ = rr({foo}, []),"
 2523:                         "rr({foo}, [], []), ok.">>),
 2524:     ?line "false.\n" = t(<<"catch_exception(true).">>),
 2525:     ?line "exception exit: restricted shell stopped"=  
 2526: 	comm_err(<<"begin shell:stop_restricted() end.">>),
 2527:     ?line "true.\n" = t(<<"catch_exception(false).">>),
 2528: 
 2529:     ?line "20\n1\n1\n1: results(2)\n2: 1\n-> 1\n3: v(2)\n-> 1.\nok.\n" = 
 2530:              t(<<"results(2). 1. v(2). h().">>),
 2531:     ?line application:unset_env(stdlib, shell_saved_results),
 2532:     ?line "1\nfoo\n17\nB = foo\nC = 17\nF = fun() ->\n           foo"
 2533:           "\n    end.\nok.\n" = 
 2534:         t(<<"begin F = fun() -> foo end, 1 end. B = F(). C = 17. b().">>),
 2535: 
 2536:     %% Tests I'd like to do: (you should try them manually)
 2537:     %% "catch spawn_link(fun() -> timer:sleep(1000), exit(foo) end)."
 2538:     %%   "** exception error: foo" should be output after 1 second
 2539:     %% "catch spawn_link(fun() -> timer:sleep(1000), 1/0 end)."
 2540:     %%   "** exception error: bad argument..." should be output after 1 second
 2541:     %% "1/0", "exit(foo)", "throw(foo)".
 2542:     %%   "h()." should show {'EXIT', {badarith,..}}, {'EXIT',{foo,...}},
 2543:     %%   and {'EXIT',{{nocatch,foo},...}}.
 2544: 
 2545:     ok.
 2546: 
 2547: otp_7184(doc) ->
 2548:     "OTP-7184. Propagate exit signals from dying evaluator process.";
 2549: otp_7184(suite) -> [];
 2550: otp_7184(Config) when is_list(Config) ->
 2551:     register(otp_7184, self()),
 2552:     ?line catch 
 2553:            t(<<"P = self(),
 2554:                 spawn_link(fun() -> process_flag(trap_exit,true),
 2555:                                     P ! up,
 2556:                                     receive X -> 
 2557:                                         otp_7184 ! {otp_7184, X}
 2558:                                     end 
 2559:                            end),
 2560:                 receive up -> ok end,
 2561:                 erlang:raise(throw, thrown, []).">>),
 2562:     receive {otp_7184,{'EXIT',_,{{nocatch,thrown},[]}}} -> ok end,
 2563: 
 2564:     ?line catch 
 2565:            t(<<"P = self(),
 2566:                 spawn_link(fun() -> process_flag(trap_exit,true),
 2567:                                     P ! up,
 2568:                                     receive X -> 
 2569:                                         otp_7184 ! {otp_7184, X}
 2570:                                     end 
 2571:                            end),
 2572:                 receive up -> ok end,
 2573:                 erlang:raise(exit, fini, []).">>),
 2574:     receive {otp_7184,{'EXIT',_,{fini,[]}}} -> ok end,
 2575: 
 2576:     ?line catch 
 2577:            t(<<"P = self(),
 2578:                 spawn_link(fun() -> process_flag(trap_exit,true),
 2579:                                     P ! up,
 2580:                                     receive X -> 
 2581:                                         otp_7184 ! {otp_7184,X}
 2582:                                     end 
 2583:                            end),
 2584:                 receive up -> ok end,
 2585:                 erlang:raise(error, bad, []).">>),
 2586:     receive {otp_7184,{'EXIT',_,{bad,[]}}} -> ok end,
 2587: 
 2588:     unregister(otp_7184),
 2589: 
 2590:     %% v/1, a few missed cases
 2591:     ?line "17\n<<0,0,0,64>>.\nok.\n" =
 2592:         t(<<"17. "
 2593:             "<<64:32>>. "
 2594:            "<<64>> = << << X >> || << X >>  <= v(2), X > v(1) >>, ok.">>),
 2595: 
 2596:     ?line "17\n<<0,17>>.\n" =t(<<"17. <<(v(1)):16>>.">>),
 2597: 
 2598:     ok.
 2599: 
 2600: otp_7232(doc) ->
 2601:     "OTP-7232. qlc:info() bug.";
 2602: otp_7232(suite) -> [];
 2603: otp_7232(Config) when is_list(Config) ->
 2604:     Info = <<"qlc:info(qlc:sort(qlc:q([X || X <- [1000,2000]]), "
 2605:              "{order, fun(A,B)-> A>B end})).">>,
 2606:     "qlc:sort([1000,2000],\n"
 2607:     "         [{order,\n"
 2608:     "           fun(A, B) ->\n"
 2609:     "                  A > B\n"
 2610:     "           end}])" = evaluate(Info, []),
 2611:     ok.
 2612: 
 2613: otp_8393(doc) ->
 2614:     "OTP-8393. Prompt string.";
 2615: otp_8393(suite) -> [];
 2616: otp_8393(Config) when is_list(Config) ->
 2617:     ?line _ = shell:prompt_func(default),
 2618:     ?line "Bad prompt function: '> '" =
 2619:         prompt_err(<<"shell:prompt_func('> ').">>),
 2620: 
 2621:     ?line _ = shell:prompt_func(default),
 2622:     ?line "exception error: an error occurred when evaluating an arithmetic expression"++_ =
 2623:         prompt_err(<<"shell:prompt_func({shell_SUITE,prompt4}).">>),
 2624: 
 2625:     ?line _ = shell:prompt_func(default),
 2626:     ?line "default.\n" =
 2627:         t(<<"shell:prompt_func({shell_SUITE,prompt2}).">>),
 2628: 
 2629:     ?line _ = shell:prompt_func(default),
 2630:     ?line "default\nl.\n" = 
 2631:         t(<<"shell:prompt_func({shell_SUITE,prompt3}). l.">>),
 2632: 
 2633:     %%
 2634:     %% Although this tests that you can set a unicode prompt function
 2635:     %% it does not really test that it does work with the io-servers.
 2636:     %% That is instead tested in the io_proto_SUITE, which has
 2637:     %% the right infrastructure in place for such tests. /PaN
 2638:     %%
 2639:     ?line _ = shell:prompt_func(default),
 2640:     ?line "default\nl.\n" = 
 2641:         t(<<"shell:prompt_func({shell_SUITE,prompt5}). l.">>),
 2642: 
 2643:     %% Restricted shell.
 2644:     Contents = <<"-module(test_restricted_shell).
 2645:                   -export([local_allowed/3, non_local_allowed/3]).
 2646:                   local_allowed(_,_,State) ->
 2647:                       {false,State}.
 2648: 
 2649:                   non_local_allowed({shell,stop_restricted},[],State) ->
 2650:                       {true,State};
 2651:                   non_local_allowed({shell,prompt_func},[_L],State) ->
 2652:                       {true,State};
 2653:                   non_local_allowed({shell_SUITE,prompt1},[_L],State) ->
 2654:                       {true,State};
 2655:                   non_local_allowed(_,_,State) ->
 2656:                       {false,State}.
 2657:                  ">>,
 2658:     ?line Test = filename:join(?config(priv_dir, Config), 
 2659: 			       "test_restricted_shell.erl"),
 2660:     ?line ok = compile_file(Config, Test, Contents, []),
 2661:     ?line _ = shell:prompt_func(default),
 2662:     ?line "exception exit: restricted shell starts now" = 
 2663: 	comm_err(<<"begin shell:start_restricted("
 2664: 			 "test_restricted_shell) end.">>),
 2665:     ?line "default.\n"++_ = 
 2666:         t(<<"shell:prompt_func({shell_SUITE,prompt1}).">>),
 2667:     ?line "exception exit: restricted shell does not allow apple(" ++ _ =
 2668: 	comm_err(<<"apple(1).">>),
 2669:     ?line "{shell_SUITE,prompt1}.\n" = 
 2670:         t(<<"shell:prompt_func(default).">>),
 2671:     ?line "exception exit: restricted shell stopped"=  
 2672: 	comm_err(<<"begin shell:stop_restricted() end.">>),
 2673:     ?line undefined = 
 2674: 	application:get_env(stdlib, restricted_shell),
 2675: 
 2676:     ?line NR = shell:results(20),
 2677:     ?line "default\n20.\n" = 
 2678:         t(<<"shell:prompt_func({shell_SUITE,prompt3}). results(0).">>),
 2679: 
 2680:     ?line _ = shell:prompt_func(default),
 2681:     ?line 0 = shell:results(NR),
 2682:     ok.
 2683: 
 2684: prompt1(_L) ->
 2685:     "prompt> ".
 2686: 
 2687: prompt2(_L) ->
 2688:     {'EXIT', []}.
 2689: 
 2690: prompt3(L) ->
 2691:     N = proplists:get_value(history, L),
 2692:     integer_to_list(N).
 2693: 
 2694: prompt4(_L) ->
 2695:     erlang:apply(fun erlang:'/'/2, [1,0]).
 2696: 
 2697: prompt5(_L) ->
 2698:     [1050,1072,1082,1074,1086,32,1077,32,85,110,105,99,111,100,101,32,63].
 2699: 
 2700: -ifdef(not_used).
 2701: exit_term(B) ->
 2702:     "** exception exit:" ++ Reply = t(B),
 2703:     S0 = string:left(Reply, string:chr(Reply, $\n)-1),
 2704:     S = string:strip(S0, right, $*),
 2705:     {ok,Ts,_} = erl_scan:string(S),
 2706:     {ok,Term} = erl_parse:parse_term(Ts),
 2707:     Term.
 2708: -endif.
 2709: 
 2710: error_string(B) ->
 2711:     "** exception error:" ++ Reply = t(B),    
 2712:     caught_string(Reply).
 2713: 
 2714: exit_string(B) ->
 2715:     "** exception exit:" ++ Reply = t(B),
 2716:     caught_string(Reply).
 2717: 
 2718: caught_string(Reply) ->
 2719:     S0 = string:left(Reply, string:chr(Reply, $\n)-1),
 2720:     S1 = string:strip(S0, right, $.),
 2721:     S2 = string:strip(S1, left, $*),
 2722:     S =  string:strip(S2, both, $ ),
 2723:     string:strip(S, both, $").
 2724: 
 2725: comm_err(B) ->
 2726:     Reply = t(B),
 2727:     S0 = string:left(Reply, string:chr(Reply, $\n)-1),
 2728:     S1 = string:strip(S0, left, $*),
 2729:     S2 = string:strip(S1, both, $ ),
 2730:     S = string:strip(S2, both, $"),
 2731:     string:strip(S, right, $.).
 2732: 
 2733: prompt_err(B) ->
 2734:     Reply = t(B),
 2735:     S00 = string:sub_string(Reply, string:chr(Reply, $\n)+1),
 2736:     S0 = string:left(S00, string:chr(S00, $\n)-1),
 2737:     S1 = string:strip(S0, left, $*),
 2738:     S2 = string:strip(S1, both, $ ),
 2739:     S = string:strip(S2, both, $"),
 2740:     string:strip(S, right, $.).
 2741: 
 2742: otp_10302(doc) ->
 2743:     "OTP-10302. Unicode.";
 2744: otp_10302(suite) -> [];
 2745: otp_10302(Config) when is_list(Config) ->
 2746:     {ok,Node} = start_node(shell_suite_helper_2,
 2747: 			   "-pa "++?config(priv_dir,Config)++
 2748: 			   " +pc unicode"),
 2749:     Test1 =
 2750:         <<"begin
 2751:                io:setopts([{encoding,utf8}]),
 2752:                [1024] = \"\\x{400}\",
 2753:                rd(rec, {a = \"\\x{400}\"}),
 2754:                ok = rl(rec)
 2755:             end.">>,
 2756:     "-record(rec,{a = \"\x{400}\"}).\nok.\n" = t({Node,Test1}),
 2757: 
 2758:     Test3 =
 2759:         <<"io:setopts([{encoding,utf8}]).
 2760:            rd(rec, {a = \"\\x{400}\"}).
 2761:            ok = rp(#rec{}).">>,
 2762:     "ok.\nrec\n#rec{a = \"\x{400}\"}.\nok.\n" = t({Node,Test3}),
 2763: 
 2764:     Test4 =
 2765:         <<"io:setopts([{encoding,utf8}]).
 2766:            A = [1024] = \"\\x{400}\".
 2767:            b().
 2768:            h().">>,
 2769: 
 2770:     "ok.\n\"\x{400}\"\nA = \"\x{400}\".\nok.\n"
 2771:     "1: io:setopts([{encoding,utf8}])\n-> ok.\n"
 2772:     "2: A = [1024] = \"\x{400}\"\n-> \"\x{400}\"\n"
 2773:     "3: b()\n-> ok.\nok.\n" = t({Node,Test4}),
 2774: 
 2775:     Test5 =
 2776:         <<"begin
 2777:                io:setopts([{encoding,utf8}]),
 2778:                results(0),
 2779:                A = [1024] = \"\\x{400}\",
 2780:                b(),
 2781:                h()
 2782:            end.">>,
 2783:     "A = \"\x{400}\".\nok.\n" = t({Node,Test5}),
 2784: 
 2785:     %% One $" is "lost":
 2786:     true =
 2787:        "\x{400}\": command not found" =:=
 2788:        prompt_err({Node,
 2789:                    <<"io:setopts([{encoding,utf8}]). v(\"\x{400}\")."/utf8>>,
 2790:                    unicode}),
 2791: 
 2792:     "ok.\ndefault\n* Bad prompt function: \"\x{400}\".\n" =
 2793:         t({Node,<<"io:setopts([{encoding,utf8}]). "
 2794:              "shell:prompt_func(\"\x{400}\")."/utf8>>,
 2795:            unicode}),
 2796:     rpc:call(Node,shell, prompt_func, [default]),
 2797:     _ = shell:prompt_func(default),
 2798: 
 2799:     %% Test lib:format_exception() (cf. OTP-6554)
 2800:     Test6 =
 2801:         <<"begin
 2802:                A = <<\"\\xaa\">>,
 2803:                S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
 2804:                {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
 2805:                {ok, Es} = erl_parse:parse_exprs(Ts),
 2806:                B = erl_eval:new_bindings(),
 2807:                erl_eval:exprs(Es, B)
 2808:            end.">>,
 2809: 
 2810:     "** exception error: an error occurred when evaluating"
 2811:         " an arithmetic expression\n     in operator  '/'/2\n"
 2812:         "        called as <<\"\xaa\">> / <<\"\xaa\">>.\n" = t(Test6),
 2813:     Test7 =
 2814:         <<"io:setopts([{encoding,utf8}]).
 2815:            A = <<\"\\xaa\">>,
 2816:            S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
 2817:            {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
 2818:            {ok, Es} = erl_parse:parse_exprs(Ts),
 2819:            B = erl_eval:new_bindings(),
 2820:            erl_eval:exprs(Es, B).">>,
 2821:     
 2822:     "ok.\n** exception error: an error occurred when evaluating"
 2823:         " an arithmetic expression\n     in operator  '/'/2\n"
 2824:         "        called as <<\"ª\">> / <<\"ª\">>.\n" = t({Node,Test7}),
 2825:     Test8 =
 2826:         <<"begin
 2827:                A = [1089],
 2828:                S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
 2829:                {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
 2830:                {ok, Es} = erl_parse:parse_exprs(Ts),
 2831:                B = erl_eval:new_bindings(),
 2832:                erl_eval:exprs(Es, B)
 2833:            end.">>,
 2834:     "** exception error: an error occurred when evaluating"
 2835:         " an arithmetic expression\n     in operator  '/'/2\n"
 2836:         "        called as [1089] / [1089].\n" = t(Test8),
 2837:     Test9 =
 2838:         <<"io:setopts([{encoding,utf8}]).
 2839:            A = [1089],
 2840:            S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
 2841:            {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
 2842:            {ok, Es} = erl_parse:parse_exprs(Ts),
 2843:            B = erl_eval:new_bindings(),
 2844:            erl_eval:exprs(Es, B).">>,
 2845: 
 2846:     "ok.\n** exception error: an error occurred when evaluating"
 2847:         " an arithmetic expression\n     in operator  '/'/2\n"
 2848:         "        called as \"\x{441}\" / \"\x{441}\".\n" = t({Node,Test9}),
 2849:     Test10 =
 2850:         <<"A = {\"1\\xaa\",
 2851:            $\\xaa,
 2852:            << <<\"hi\">>/binary >>,
 2853:            <<\"1\xaa\">>},
 2854:            fun(a) -> true end(A).">>,
 2855:     "** exception error: no function clause matching \n"
 2856:     "                    erl_eval:'-inside-an-interpreted-fun-'"
 2857:     "({\"1\xc2\xaa\",170,<<\"hi\">>,\n                                    "
 2858:     "                        <<\"1\xc2\xaa\">>}) .\n" = t(Test10),
 2859:     Test11 =
 2860:         <<"io:setopts([{encoding,utf8}]).
 2861:            A = {\"1\\xaa\",
 2862:            $\\xaa,
 2863:            << <<\"hi\">>/binary >>,
 2864:            <<\"1\xaa\">>},
 2865:            fun(a) -> true end(A).">>,
 2866: 
 2867:     "ok.\n** exception error: no function clause matching \n"
 2868:     "                    erl_eval:'-inside-an-interpreted-fun-'"
 2869:     "({\"1\xaa\",170,<<\"hi\">>,\n                                           "
 2870:     "                 <<\"1\xaa\"/utf8>>}) .\n"  = t({Node,Test11}),
 2871:     Test12 = <<"fun(a, b) -> false end(65, [1089]).">>,
 2872:     "** exception error: no function clause matching \n"
 2873:     "                    erl_eval:'-inside-an-interpreted-fun-'(65,[1089])"
 2874:     " .\n" = t(Test12),
 2875:     Test13 =
 2876:         <<"io:setopts([{encoding,utf8}]).
 2877:            fun(a, b) -> false end(65, [1089]).">>,
 2878:     "ok.\n** exception error: no function clause matching \n"
 2879:     "                    erl_eval:'-inside-an-interpreted-fun-'(65,\"\x{441}\")"
 2880:     " .\n" = t({Node,Test13}),
 2881: 
 2882:     test_server:stop_node(Node),
 2883:     ok.
 2884: 
 2885: scan(B) ->
 2886:     F = fun(Ts) -> 
 2887:                 case erl_parse:parse_term(Ts) of
 2888:                     {ok,Term} ->
 2889:                         Term;
 2890:                     _Error ->
 2891:                         {ok,Form} = erl_parse:parse_form(Ts),
 2892:                         Form
 2893:                 end
 2894:         end,
 2895:     scan(t(B), F).
 2896: 
 2897: scan(S0, F) ->
 2898:     case erl_scan:tokens([], S0, 1, [unicode]) of
 2899:         {done,{ok,Ts,_},S} ->
 2900:             [F(Ts) | scan(S, F)];
 2901:         _Else ->
 2902:             []
 2903:     end.
 2904: 
 2905: t({Node,Bin,Enc}) when is_atom(Node),is_binary(Bin), is_atom(Enc) ->
 2906:     t0({Bin,Enc}, fun() -> start_new_shell(Node) end);
 2907: t({Node,Bin}) when is_atom(Node),is_binary(Bin) ->
 2908:     t0({Bin,latin1}, fun() -> start_new_shell(Node) end);
 2909: t(Bin) when is_binary(Bin) ->
 2910:     t0({Bin,latin1}, fun() -> start_new_shell() end);
 2911: t({Bin,Enc}) when is_binary(Bin), is_atom(Enc) ->
 2912:     t0({Bin,Enc}, fun() -> start_new_shell() end);
 2913: t(L) ->
 2914:     t(list_to_binary(L)).
 2915: 
 2916: t0({Bin,Enc}, F) ->
 2917:     %% Spawn a process so that io_request messages do not interfer.
 2918:     P = self(),
 2919:     C = spawn(fun() -> t1(P, {Bin, Enc}, F) end),
 2920:     receive {C, R} -> R end.
 2921: 
 2922: t1(Parent, {Bin,Enc}, F) ->
 2923:     io:format("*** Testing ~s~n", [binary_to_list(Bin)]),
 2924:     S = #state{bin = Bin, unic = Enc, reply = [], leader = group_leader()},
 2925:     group_leader(self(), self()),
 2926:     _Shell = F(),
 2927:     try 
 2928:         server_loop(S)
 2929:     catch exit:R -> Parent ! {self(), R};
 2930:           throw:{?MODULE,LoopReply,latin1} ->
 2931:                    L0 = binary_to_list(list_to_binary(LoopReply)),
 2932:                    [$\n | L1] = lists:dropwhile(fun(X) -> X =/= $\n end, L0),
 2933:                    Parent ! {self(), dotify(L1)};
 2934:           throw:{?MODULE,LoopReply,_Uni} ->
 2935:                    Tmp = unicode:characters_to_binary(LoopReply),
 2936:                    L0 = unicode:characters_to_list(Tmp),
 2937:                    [$\n | L1] = lists:dropwhile(fun(X) -> X =/= $\n end, L0),
 2938:                    Parent ! {self(), dotify(L1)}
 2939:     after group_leader(S#state.leader, self())
 2940:     end.
 2941: 
 2942: dotify([$., $\n | L]) ->
 2943:     [$., $\n | dotify(L)];
 2944: dotify([$,, $\n | L]) ->
 2945:     [$,, $\n | dotify(L)];
 2946: dotify("ok\n" ++ L) ->
 2947:     "ok.\n" ++ dotify(L);
 2948: dotify("\nok\n" ++ L) ->
 2949:     ".\nok.\n" ++ dotify(L);
 2950: dotify([$\n]) ->
 2951:     [$., $\n];
 2952: dotify([C | L]) ->
 2953:     [C | dotify(L)];
 2954: dotify([]) ->
 2955:     [].
 2956: 
 2957: start_new_shell() ->
 2958:     Shell = shell:start(),
 2959:     link(Shell),
 2960:     Shell.
 2961: 
 2962: start_new_shell(Node) ->
 2963:     Shell = rpc:call(Node,shell,start,[]),
 2964:     link(Shell),
 2965:     Shell.
 2966: 
 2967: %% This is a very minimal implementation of the IO protocol...
 2968: 
 2969: server_loop(S) ->
 2970:     receive 
 2971:         {io_request, From, ReplyAs, Request} when is_pid(From) ->
 2972: 	    server_loop(do_io_request(Request, From, S, ReplyAs));
 2973: 	NotExpected ->
 2974:             exit(NotExpected)
 2975:     end.
 2976:             
 2977: do_io_request(Req, From, S, ReplyAs) ->
 2978:     case io_requests([Req], [], S) of
 2979:         {_Status,{eof,_},S1} ->
 2980: 	    io_reply(From, ReplyAs, {error,terminated}),
 2981: 	    throw({?MODULE,S1#state.reply,S1#state.unic});
 2982: 	{_Status,Reply,S1} ->
 2983: 	    io_reply(From, ReplyAs, Reply),
 2984: 	    S1
 2985:     end.
 2986: 
 2987: io_reply(From, ReplyAs, Reply) ->
 2988:     From ! {io_reply, ReplyAs, Reply}.
 2989: 
 2990: io_requests([{requests, Rs1} | Rs], Cont, S) ->
 2991:     io_requests(Rs1, [Rs | Cont], S);
 2992: io_requests([R | Rs], Cont, S) ->
 2993:     case io_request(R, S) of
 2994:         {ok, ok, S1} ->
 2995:             io_requests(Rs, Cont, S1);
 2996:         Reply ->
 2997:             Reply
 2998:     end;
 2999: io_requests([], [Rs|Cont], S) ->
 3000:     io_requests(Rs, Cont, S);
 3001: io_requests([], [], S) -> 
 3002:     {ok,ok,S}.
 3003: 
 3004: io_request({setopts, Opts}, S) ->
 3005:     #state{unic = OldEnc, bin = Bin} = S,
 3006:     NewEnc = case proplists:get_value(encoding, Opts) of
 3007:                  undefined -> OldEnc;
 3008:                  utf8 -> unicode;
 3009:                  New -> New
 3010:              end,
 3011:     NewBin = case {OldEnc, NewEnc} of
 3012:                  {E, E} -> Bin;
 3013:                  {latin1, _} ->
 3014:                      unicode:characters_to_binary(Bin, latin1, unicode);
 3015:                  {_, latin1} ->
 3016:                      unicode:characters_to_binary(Bin, unicode, latin1);
 3017:                  {_, _} -> Bin
 3018:              end,
 3019:     {ok, ok, S#state{unic = NewEnc, bin = NewBin}};
 3020: io_request(getopts, S) ->
 3021:     {ok,[{encoding,S#state.unic}],S};
 3022: io_request({get_geometry,columns}, S) ->
 3023:     {ok,80,S};
 3024: io_request({get_geometry,rows}, S) ->
 3025:     {ok,24,S};
 3026: io_request({put_chars,Chars}, S) ->
 3027:     {ok,ok,S#state{reply = [S#state.reply | Chars]}};
 3028: io_request({put_chars,latin1,Chars}, S) ->
 3029:     {ok,ok,S#state{reply = [S#state.reply | Chars]}};
 3030: io_request({put_chars,unicode,Chars0}, S) ->
 3031:     Chars = unicode:characters_to_list(Chars0),
 3032:     {ok,ok,S#state{reply = [S#state.reply | Chars]}};
 3033: io_request({put_chars,Mod,Func,Args}, S) ->
 3034:     case catch apply(Mod, Func, Args) of
 3035:         Chars when is_list(Chars) -> 
 3036:             io_request({put_chars,Chars}, S)
 3037:     end;
 3038: io_request({put_chars,Enc,Mod,Func,Args}, S) ->
 3039:     case catch apply(Mod, Func, Args) of
 3040:         Chars when is_list(Chars) -> 
 3041:             io_request({put_chars,Enc,Chars}, S)
 3042:     end;
 3043: io_request({get_until,_Prompt,Mod,Func,ExtraArgs}, S) ->
 3044:     get_until(Mod, Func, ExtraArgs, S, latin1);
 3045: io_request({get_until,Enc,_Prompt,Mod,Func,ExtraArgs}, S) ->
 3046:     get_until(Mod, Func, ExtraArgs, S, Enc).
 3047: 
 3048: get_until(Mod, Func, ExtraArgs, S, Enc) ->
 3049:     get_until_loop(Mod, Func, ExtraArgs, S, {more,[]}, Enc).
 3050: 
 3051: get_until_loop(M, F, As, S, {more,Cont}, Enc) ->
 3052:     Bin = S#state.bin,
 3053:     case byte_size(Bin) of
 3054:         0 ->
 3055:             get_until_loop(M, F, As, S, 
 3056:                            catch apply(M, F, [Cont,eof|As]), Enc);
 3057: 	_ when S#state.unic =:= latin1 ->
 3058: 	    get_until_loop(M, F, As, S#state{bin = <<>>},
 3059: 			   catch apply(M, F, [Cont,binary_to_list(Bin)|As]), Enc);
 3060: 	_ ->
 3061: 	    get_until_loop(M, F, As, S#state{bin = <<>>},
 3062: 			   catch apply(M, F, [Cont,unicode:characters_to_list(Bin)|As]), Enc)
 3063:     end;
 3064: get_until_loop(_M, _F, _As, S, {done,Res,Buf}, Enc) ->
 3065:     {ok,Res,S#state{bin = buf2bin(Buf, Enc)}};
 3066: get_until_loop(_M, F, _As, S, _Other, _Enc) ->
 3067:     {error,{error,F},S}.
 3068: 
 3069: buf2bin(eof,_) ->
 3070:     <<>>;
 3071: buf2bin(Buf,latin1) ->
 3072:     list_to_binary(Buf);
 3073: buf2bin(Buf,utf8) ->
 3074:     unicode:characters_to_binary(Buf,unicode,unicode);
 3075: buf2bin(Buf,unicode) ->
 3076:     unicode:characters_to_binary(Buf,unicode,unicode).
 3077: 
 3078: run_file(Config, Module, Test) ->
 3079:     FileName = filename(lists:concat([Module, ".erl"]), Config),
 3080:     BeamFile = filename(lists:concat([Module, ".beam"]), Config),
 3081:     LoadBeamFile = filename(Module, Config),
 3082:     ok = file:write_file(FileName, Test),
 3083:     ok = compile_file(Config, FileName, Test, []),
 3084:     code:purge(Module),
 3085:     {module, Module} = code:load_abs(LoadBeamFile), 
 3086:     ok = Module:t(),
 3087:     file:delete(FileName),
 3088:     file:delete(BeamFile),
 3089:     ok.
 3090: 
 3091: compile_file(Config, File, Test, Opts0) ->
 3092:     ?line Opts = [export_all,return,{outdir,?config(priv_dir, Config)}|Opts0],
 3093:     ?line ok = file:write_file(File, Test),
 3094:     ?line case compile:file(File, Opts) of
 3095:               {ok, _M, _Ws} -> ok;
 3096:               _ -> error
 3097:           end.
 3098: 
 3099: filename(Name, Config) when is_atom(Name) ->
 3100:     filename(atom_to_list(Name), Config);
 3101: filename(Name, Config) ->
 3102:     filename:join(?config(priv_dir, Config), Name).
 3103: 
 3104: start_node(Name, Xargs) ->
 3105:     ?line N = test_server:start_node(Name, slave, [{args, " " ++ Xargs}]),
 3106:     global:sync(),
 3107:     N.
 3108: