diff options
Diffstat (limited to 'lib/stdlib')
158 files changed, 11392 insertions, 9318 deletions
diff --git a/lib/stdlib/doc/specs/.gitignore b/lib/stdlib/doc/specs/.gitignore new file mode 100644 index 0000000000..322eebcb06 --- /dev/null +++ b/lib/stdlib/doc/specs/.gitignore @@ -0,0 +1 @@ +specs_*.xml diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile index b558697d63..16e0a86e3b 100644 --- a/lib/stdlib/doc/src/Makefile +++ b/lib/stdlib/doc/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2010. All Rights Reserved. +# Copyright Ericsson AB 1997-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -125,18 +125,24 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf +SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml) + +TOP_SPECS_FILE = specs.xml + # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- XML_FLAGS += +SPECS_FLAGS = -I../../include -I../../../kernel/include + # ---------------------------------------------------- # Targets # ---------------------------------------------------- $(HTMLDIR)/%.gif: %.gif $(INSTALL_DATA) $< $@ -docs: pdf html man +docs: man pdf html $(TOP_PDF_FILE): $(XML_FILES) @@ -155,8 +161,13 @@ clean clean_docs: rm -f $(MAN3DIR)/* rm -f $(MAN6DIR)/* rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f $(SPECDIR)/* rm -f errs core *~ +$(SPECDIR)/specs_erl_id_trans.xml: + escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module erl_id_trans + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml index 5c3ac6a2a9..a79fcd487e 100644 --- a/lib/stdlib/doc/src/array.xml +++ b/lib/stdlib/doc/src/array.xml @@ -3,7 +3,7 @@ <erlref> <header> <copyright> - <year>2007</year><year>2009</year> + <year>2007</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -82,19 +82,35 @@ the default value cannot be confused with the values of set entries.</p> %% allow accesses beyond the last set entry {'EXIT',{badarg,_}} = (catch array:set(18, true, A3)). {'EXIT',{badarg,_}} = (catch array:get(18, A3)).</pre></description> -<section><title>DATA TYPES</title><marker id="types"/> - -<taglist> -<tag><c>array()</c></tag> -<item><marker id="type-array"/> -<p>A functional, extendible array. The representation is - not documented and is subject to change without notice. Note that - arrays cannot be directly compared for equality.</p> -</item> -</taglist></section> +<datatypes> + <datatype> + <name><marker id="type-array">array()</marker></name> + <desc> + <p>A functional, extendible array. The representation is + not documented and is subject to change without notice. Note that + arrays cannot be directly compared for equality.</p> + </desc> + </datatype> + <datatype> + <name name="array_indx"/> + </datatype> + <datatype> + <name name="array_opts"/> + </datatype> + <datatype> + <name name="array_opt"/> + </datatype> + <datatype> + <name name="indx_pairs"/> + </datatype> + <datatype> + <name name="indx_pair"/> + </datatype> +</datatypes> + <funcs> <func> -<name>default(Array::array()) -> term()</name> +<name name="default" arity="1"/> <fsummary>Get the value used for uninitialized entries.</fsummary> <desc><marker id="default-1"/> @@ -104,7 +120,7 @@ the default value cannot be confused with the values of set entries.</p> <p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>.</p> </desc></func> <func> -<name>fix(Array::array()) -> array()</name> +<name name="fix" arity="1"/> <fsummary>Fix the size of the array.</fsummary> <desc><marker id="fix-1"/> @@ -114,105 +130,100 @@ the default value cannot be confused with the values of set entries.</p> <p><em>See also:</em> <seealso marker="#relax-1">relax/1</seealso>.</p> </desc></func> <func> -<name>foldl(Function, InitialAcc::term(), Array::array()) -> term()</name> +<name name="foldl" arity="3"/> <fsummary>Fold the elements of the array using the given function and initial accumulator value.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term(), Acc::term()) -> term()</v></type> <desc><marker id="foldl-3"/> - <p>Fold the elements of the array using the given function and initial accumulator value. The elements are visited in order from the - lowest index to the highest. If <c>Function</c> is not a function, the + lowest index to the highest. If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#map-2">map/2</seealso>, <seealso marker="#sparse_foldl-3">sparse_foldl/3</seealso>.</p> </desc></func> <func> -<name>foldr(Function, InitialAcc::term(), Array::array()) -> term()</name> +<name name="foldr" arity="3"/> <fsummary>Fold the elements of the array right-to-left using the given function and initial accumulator value.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term(), Acc::term()) -> term()</v></type> <desc><marker id="foldr-3"/> <p>Fold the elements of the array right-to-left using the given function and initial accumulator value. The elements are visited in - order from the highest index to the lowest. If <c>Function</c> is not a + order from the highest index to the lowest. If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#map-2">map/2</seealso>.</p> </desc></func> <func> -<name>from_list(List::list()) -> array()</name> +<name name="from_list" arity="1"/> <fsummary>Equivalent to from_list(List, undefined). </fsummary> <desc><marker id="from_list-1"/> -<p>Equivalent to <seealso marker="#from_list-2">from_list(List, undefined)</seealso>.</p> +<p>Equivalent to <seealso marker="#from_list-2">from_list(<anno>List</anno>, undefined)</seealso>.</p> </desc></func> <func> -<name>from_list(List::list(), Default::term()) -> array()</name> +<name name="from_list" arity="2"/> <fsummary>Convert a list to an extendible array.</fsummary> <desc><marker id="from_list-2"/> -<p>Convert a list to an extendible array. <c>Default</c> is used as the value - for uninitialized entries of the array. If <c>List</c> is not a proper list, +<p>Convert a list to an extendible array. <c><anno>Default</anno></c> is used as the value + for uninitialized entries of the array. If <c><anno>List</anno></c> is not a proper list, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#to_list-1">to_list/1</seealso>.</p> </desc></func> <func> -<name>from_orddict(Orddict::list()) -> array()</name> +<name name="from_orddict" arity="1"/> <fsummary>Equivalent to from_orddict(Orddict, undefined). </fsummary> <desc><marker id="from_orddict-1"/> -<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(Orddict, undefined)</seealso>.</p> +<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(<anno>Orddict</anno>, undefined)</seealso>.</p> </desc></func> <func> -<name>from_orddict(List::list(), Default::term()) -> array()</name> +<name name="from_orddict" arity="2"/> <fsummary>Convert an ordered list of pairs {Index, Value} to a corresponding extendible array.</fsummary> <desc><marker id="from_orddict-2"/> <p>Convert an ordered list of pairs <c>{Index, Value}</c> to a - corresponding extendible array. <c>Default</c> is used as the value for - uninitialized entries of the array. If <c>List</c> is not a proper, + corresponding extendible array. <c><anno>Default</anno></c> is used as the value for + uninitialized entries of the array. If <c><anno>Orddict</anno></c> is not a proper, ordered list of pairs whose first elements are nonnegative integers, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#to_orddict-1">to_orddict/1</seealso>.</p> </desc></func> <func> -<name>get(I::integer(), Array::array()) -> term()</name> +<name name="get" arity="2"/> <fsummary>Get the value of entry I.</fsummary> <desc><marker id="get-2"/> -<p>Get the value of entry <c>I</c>. If <c>I</c> is not a nonnegative - integer, or if the array has fixed size and <c>I</c> is larger than the +<p>Get the value of entry <c><anno>I</anno></c>. If <c><anno>I</anno></c> is not a nonnegative + integer, or if the array has fixed size and <c><anno>I</anno></c> is larger than the maximum index, the call fails with reason <c>badarg</c>.</p> <p>If the array does not have fixed size, this function will return the - default value for any index <c>I</c> greater than <c>size(Array)-1</c>.</p> + default value for any index <c><anno>I</anno></c> greater than <c>size(<anno>Array</anno>)-1</c>.</p> <p><em>See also:</em> <seealso marker="#set-3">set/3</seealso>.</p> </desc></func> <func> -<name>is_array(X::term()) -> bool()</name> +<name name="is_array" arity="1"/> <fsummary>Returns true if X appears to be an array, otherwise false.</fsummary> <desc><marker id="is_array-1"/> -<p>Returns <c>true</c> if <c>X</c> appears to be an array, otherwise <c>false</c>. - Note that the check is only shallow; there is no guarantee that <c>X</c> +<p>Returns <c>true</c> if <c><anno>X</anno></c> appears to be an array, otherwise <c>false</c>. + Note that the check is only shallow; there is no guarantee that <c><anno>X</anno></c> is a well-formed array representation even if this function returns <c>true</c>.</p> </desc></func> <func> -<name>is_fix(Array::array()) -> bool()</name> +<name name="is_fix" arity="1"/> <fsummary>Check if the array has fixed size.</fsummary> <desc><marker id="is_fix-1"/> @@ -222,20 +233,18 @@ the default value cannot be confused with the values of set entries.</p> <p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>.</p> </desc></func> <func> -<name>map(Function, Array::array()) -> array()</name> +<name name="map" arity="2"/> <fsummary>Map the given function onto each element of the array.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term()) -> term()</v></type> <desc><marker id="map-2"/> <p>Map the given function onto each element of the array. The elements are visited in order from the lowest index to the highest. - If <c>Function</c> is not a function, the call fails with reason <c>badarg</c>. + If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#sparse_map-2">sparse_map/2</seealso>.</p> </desc></func> <func> -<name>new() -> array()</name> +<name name="new" arity="0"/> <fsummary>Create a new, extendible array with initial size zero.</fsummary> <desc><marker id="new-0"/> @@ -244,7 +253,7 @@ the default value cannot be confused with the values of set entries.</p> <p><em>See also:</em> <seealso marker="#new-1">new/1</seealso>, <seealso marker="#new-2">new/2</seealso>.</p> </desc></func> <func> -<name>new(Options::term()) -> array()</name> +<name name="new" arity="1"/> <fsummary>Create a new array according to the given options.</fsummary> <desc><marker id="new-1"/> @@ -253,10 +262,10 @@ the default value cannot be confused with the values of set entries.</p> the array is extendible and has initial size zero. Array indices start at 0.</p> - <p><c>Options</c> is a single term or a list of terms, selected from the + <p><c><anno>Options</anno></c> is a single term or a list of terms, selected from the following: </p><taglist> - <tag><c>N::integer()</c> or <c>{size, N::integer()}</c></tag> + <tag><c>N::integer() >= 0</c> or <c>{size, N::integer() >= 0}</c></tag> <item><p>Specifies the initial size of the array; this also implies <c>{fixed, true}</c>. If <c>N</c> is not a nonnegative integer, the call fails with reason <c>badarg</c>.</p></item> @@ -283,19 +292,19 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>, <seealso marker="#from_list-2">from_list/2</seealso>, <seealso marker="#get-2">get/2</seealso>, <seealso marker="#new-0">new/0</seealso>, <seealso marker="#new-2">new/2</seealso>, <seealso marker="#set-3">set/3</seealso>.</p> </desc></func> <func> -<name>new(Size::integer(), Options::term()) -> array()</name> +<name name="new" arity="2"/> <fsummary>Create a new array according to the given size and options.</fsummary> <desc><marker id="new-2"/> <p>Create a new array according to the given size and options. If - <c>Size</c> is not a nonnegative integer, the call fails with reason + <c><anno>Size</anno></c> is not a nonnegative integer, the call fails with reason <c>badarg</c>. By default, the array has fixed size. Note that any size - specifications in <c>Options</c> will override the <c>Size</c> parameter.</p> + specifications in <c><anno>Options</anno></c> will override the <c><anno>Size</anno></c> parameter.</p> - <p>If <c>Options</c> is a list, this is simply equivalent to <c>new([{size, - Size} | Options]</c>, otherwise it is equivalent to <c>new([{size, Size} | - [Options]]</c>. However, using this function directly is more efficient.</p> + <p>If <c><anno>Options</anno></c> is a list, this is simply equivalent to <c>new([{size, + <anno>Size</anno>} | <anno>Options</anno>]</c>, otherwise it is equivalent to <c>new([{size, <anno>Size</anno>} | + [<anno>Options</anno>]]</c>. However, using this function directly is more efficient.</p> <p>Example: </p><pre> array:new(100, {default,0})</pre><p> creates a fixed-size array of size @@ -304,7 +313,7 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#new-1">new/1</seealso>.</p> </desc></func> <func> -<name>relax(Array::array()) -> array()</name> +<name name="relax" arity="1"/> <fsummary>Make the array resizable.</fsummary> <desc><marker id="relax-1"/> @@ -313,24 +322,24 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>.</p> </desc></func> <func> -<name>reset(I::integer(), Array::array()) -> array()</name> +<name name="reset" arity="2"/> <fsummary>Reset entry I to the default value for the array.</fsummary> <desc><marker id="reset-2"/> -<p>Reset entry <c>I</c> to the default value for the array. - If the value of entry <c>I</c> is the default value the array will be +<p>Reset entry <c><anno>I</anno></c> to the default value for the array. + If the value of entry <c><anno>I</anno></c> is the default value the array will be returned unchanged. Reset will never change size of the array. Shrinking can be done explicitly by calling <seealso marker="#resize-2">resize/2</seealso>.</p> - <p>If <c>I</c> is not a nonnegative integer, or if the array has fixed size - and <c>I</c> is larger than the maximum index, the call fails with reason + <p>If <c><anno>I</anno></c> is not a nonnegative integer, or if the array has fixed size + and <c><anno>I</anno></c> is larger than the maximum index, the call fails with reason <c>badarg</c>; cf. <seealso marker="#set-3">set/3</seealso> </p> <p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#set-3">set/3</seealso>.</p> </desc></func> <func> -<name>resize(Array::array()) -> array()</name> +<name name="resize" arity="1"/> <fsummary>Change the size of the array to that reported by sparse_size/1.</fsummary> <desc><marker id="resize-1"/> @@ -340,90 +349,84 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#resize-2">resize/2</seealso>, <seealso marker="#sparse_size-1">sparse_size/1</seealso>.</p> </desc></func> <func> -<name>resize(Size::integer(), Array::array()) -> array()</name> +<name name="resize" arity="2"/> <fsummary>Change the size of the array.</fsummary> <desc><marker id="resize-2"/> -<p>Change the size of the array. If <c>Size</c> is not a nonnegative +<p>Change the size of the array. If <c><anno>Size</anno></c> is not a nonnegative integer, the call fails with reason <c>badarg</c>. If the given array has fixed size, the resulting array will also have fixed size.</p> </desc></func> <func> -<name>set(I::integer(), Value::term(), Array::array()) -> array()</name> +<name name="set" arity="3"/> <fsummary>Set entry I of the array to Value.</fsummary> <desc><marker id="set-3"/> -<p>Set entry <c>I</c> of the array to <c>Value</c>. If <c>I</c> is not a - nonnegative integer, or if the array has fixed size and <c>I</c> is larger +<p>Set entry <c><anno>I</anno></c> of the array to <c><anno>Value</anno></c>. If <c><anno>I</anno></c> is not a + nonnegative integer, or if the array has fixed size and <c><anno>I</anno></c> is larger than the maximum index, the call fails with reason <c>badarg</c>.</p> - <p>If the array does not have fixed size, and <c>I</c> is greater than - <c>size(Array)-1</c>, the array will grow to size <c>I+1</c>. + <p>If the array does not have fixed size, and <c><anno>I</anno></c> is greater than + <c>size(<anno>Array</anno>)-1</c>, the array will grow to size <c><anno>I</anno>+1</c>. </p> <p><em>See also:</em> <seealso marker="#get-2">get/2</seealso>, <seealso marker="#reset-2">reset/2</seealso>.</p> </desc></func> <func> -<name>size(Array::array()) -> integer()</name> +<name name="size" arity="1"/> <fsummary>Get the number of entries in the array.</fsummary> <desc><marker id="size-1"/> <p>Get the number of entries in the array. Entries are numbered - from 0 to <c>size(Array)-1</c>; hence, this is also the index of the first + from 0 to <c>size(<anno>Array</anno>)-1</c>; hence, this is also the index of the first entry that is guaranteed to not have been previously set.</p> <p><em>See also:</em> <seealso marker="#set-3">set/3</seealso>, <seealso marker="#sparse_size-1">sparse_size/1</seealso>.</p> </desc></func> <func> -<name>sparse_foldl(Function, InitialAcc::term(), Array::array()) -> term()</name> +<name name="sparse_foldl" arity="3"/> <fsummary>Fold the elements of the array using the given function and initial accumulator value, skipping default-valued entries.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term(), Acc::term()) -> term()</v></type> <desc><marker id="sparse_foldl-3"/> <p>Fold the elements of the array using the given function and initial accumulator value, skipping default-valued entries. The elements are visited in order from the lowest index to the highest. - If <c>Function</c> is not a function, the call fails with reason <c>badarg</c>. + If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#sparse_foldr-3">sparse_foldr/3</seealso>.</p> </desc></func> <func> -<name>sparse_foldr(Function, InitialAcc::term(), Array::array()) -> term()</name> +<name name="sparse_foldr" arity="3"/> <fsummary>Fold the elements of the array right-to-left using the given function and initial accumulator value, skipping default-valued entries.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term(), Acc::term()) -> term()</v></type> <desc><marker id="sparse_foldr-3"/> <p>Fold the elements of the array right-to-left using the given function and initial accumulator value, skipping default-valued entries. The elements are visited in order from the highest index to - the lowest. If <c>Function</c> is not a function, the call fails with + the lowest. If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#sparse_foldl-3">sparse_foldl/3</seealso>.</p> </desc></func> <func> -<name>sparse_map(Function, Array::array()) -> array()</name> +<name name="sparse_map" arity="2"/> <fsummary>Map the given function onto each element of the array, skipping default-valued entries.</fsummary> -<type> -<v>Function = (Index::integer(), Value::term()) -> term()</v></type> <desc><marker id="sparse_map-2"/> <p>Map the given function onto each element of the array, skipping default-valued entries. The elements are visited in order from the - lowest index to the highest. If <c>Function</c> is not a function, the + lowest index to the highest. If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>. </p> <p><em>See also:</em> <seealso marker="#map-2">map/2</seealso>.</p> </desc></func> <func> -<name>sparse_size(A::array()) -> integer()</name> +<name name="sparse_size" arity="1"/> <fsummary>Get the number of entries in the array up until the last non-default valued entry.</fsummary> @@ -436,7 +439,7 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#resize-1">resize/1</seealso>, <seealso marker="#size-1">size/1</seealso>.</p> </desc></func> <func> -<name>sparse_to_list(Array::array()) -> list()</name> +<name name="sparse_to_list" arity="1"/> <fsummary>Converts the array to a list, skipping default-valued entries.</fsummary> <desc><marker id="sparse_to_list-1"/> @@ -446,7 +449,7 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#to_list-1">to_list/1</seealso>.</p> </desc></func> <func> -<name>sparse_to_orddict(Array::array()) -> [{Index::integer(), Value::term()}]</name> +<name name="sparse_to_orddict" arity="1"/> <fsummary>Convert the array to an ordered list of pairs {Index, Value}, skipping default-valued entries.</fsummary> @@ -458,7 +461,7 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#to_orddict-1">to_orddict/1</seealso>.</p> </desc></func> <func> -<name>to_list(Array::array()) -> list()</name> +<name name="to_list" arity="1"/> <fsummary>Converts the array to a list.</fsummary> <desc><marker id="to_list-1"/> @@ -468,7 +471,7 @@ cannot be changed once the array has been created.</p> <p><em>See also:</em> <seealso marker="#from_list-2">from_list/2</seealso>, <seealso marker="#sparse_to_list-1">sparse_to_list/1</seealso>.</p> </desc></func> <func> -<name>to_orddict(Array::array()) -> [{Index::integer(), Value::term()}]</name> +<name name="to_orddict" arity="1"/> <fsummary>Convert the array to an ordered list of pairs {Index, Value}.</fsummary> <desc><marker id="to_orddict-1"/> diff --git a/lib/stdlib/doc/src/base64.xml b/lib/stdlib/doc/src/base64.xml index d3fd7a843b..bfe8494a73 100644 --- a/lib/stdlib/doc/src/base64.xml +++ b/lib/stdlib/doc/src/base64.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2007</year><year>2009</year> + <year>2007</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -33,32 +33,33 @@ <description> <p>Implements base 64 encode and decode, see RFC2045. </p> </description> + <datatypes> + <datatype> + <name name="ascii_string"/> + </datatype> + </datatypes> <funcs> <func> - <name>encode(Data) -> Base64 </name> - <name>encode_to_string(Data) -> Base64String</name> + <name name="encode" arity="1"/> + <name name="encode_to_string" arity="1"/> <fsummary>Encodes data into base64. </fsummary> - <type> - <v>Data = string() | binary()</v> - <v>Base64 = binary()</v> - <v>Base64String = string()</v> - </type> + <type variable="Data"/> + <type variable="Base64" name_i="1"/> + <type variable="Base64String"/> <desc> <p>Encodes a plain ASCII string into base64. The result will be 33% larger than the data.</p> </desc> </func> <func> - <name>decode(Base64) -> Data</name> - <name>decode_to_string(Base64) -> DataString</name> - <name>mime_decode(Base64) -> Data</name> - <name>mime_decode_to_string(Base64) -> DataString</name> + <name name="decode" arity="1"/> + <name name="decode_to_string" arity="1"/> + <name name="mime_decode" arity="1"/> + <name name="mime_decode_to_string" arity="1"/> <fsummary>Decodes a base64 encoded string to data. </fsummary> - <type> - <v>Base64 = string() | binary()</v> - <v>Data = binary()</v> - <v>DataString = string()</v> - </type> + <type variable="Base64" name_i="1"/> + <type variable="Data" name_i="1"/> + <type variable="DataString" name_i="2"/> <desc> <p>Decodes a base64 encoded string to plain ASCII. See RFC4648. <c>mime_decode/1</c> and <c>mime_decode_to_string/1</c> diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index adc411e272..db65eb3848 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2010</year> + <year>2000</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -88,7 +88,6 @@ it is recommended that it contains at least 32 characters and that both upper and lower case letters as well as digits and special characters are used.</p> - <p></p> <p>The default type -- and currently the only type -- of crypto algorithm is <c>des3_cbc</c>, three rounds of DES. The key string will be scrambled using <c>erlang:md5/1</c> to generate @@ -154,70 +153,78 @@ </section> </section> - <section> - <title>DATA TYPES</title> - <code type="none"> -beam() -> Module | Filename | binary() - Module = atom() - Filename = string() | atom()</code> - <p>Each of the functions described below accept either the module - name, the filename, or a binary containing the beam module.</p> - <code type="none"> -chunkdata() = {ChunkId, DataB} | {ChunkName, DataT} - ChunkId = chunkid() - DataB = binary() - {ChunkName, DataT} = - {abstract_code, AbstractCode} - | {attributes, [{Attribute, [AttributeValue]}]} - | {compile_info, [{InfoKey, [InfoValue]}]} - | {exports, [{Function, Arity}]} - | {labeled_exports, [{Function, Arity, Label}]} - | {imports, [{Module, Function, Arity}]} - | {indexed_imports, [{Index, Module, Function, Arity}]} - | {locals, [{Function, Arity}]}]} - | {labeled_locals, [{Function, Arity, Label}]}]} - | {atoms, [{integer(), atom()}]} - AbstractCode = {AbstVersion, Forms} | no_abstract_code - AbstVersion = atom() - Attribute = atom() - AttributeValue = term() - Module = Function = atom() - Arity = int() - Label = int()</code> - <p>It is not checked that the forms conform to the abstract format - indicated by <c>AbstVersion</c>. <c>no_abstract_code</c> means - that the <c>"Abst"</c> chunk is present, but empty.</p> - <p>The list of attributes is sorted on <c>Attribute</c>, and each - attribute name occurs once in the list. The attribute values - occur in the same order as in the file. The lists of functions - are also sorted.</p> - <code type="none"> -chunkid() = "Abst" | "Attr" | "CInf" - | "ExpT" | "ImpT" | "LocT" - | "Atom" + <datatypes> + <datatype> + <name name="beam"/> + <desc> + <p>Each of the functions described below accept either the + module name, the filename, or a binary containing the beam + module.</p> + </desc> + </datatype> + <datatype> + <name name="chunkdata"/> + <desc> + <p>The list of attributes is sorted on <c>Attribute</c> + (in attrib_entry()), and each + attribute name occurs once in the list. The attribute values + occur in the same order as in the file. The lists of functions + are also sorted.</p> + </desc> + </datatype> + <datatype> + <name name="chunkid"/> + <desc> + <p>"Abst" | "Attr" | "CInf" | "ExpT" | "ImpT" | "LocT" | "Atom"</p> + </desc> + </datatype> + <datatype> + <name name="dataB"/> + </datatype> + <datatype> + <name name="abst_code"/> + <desc> + <p>It is not checked that the forms conform to the abstract format + indicated by <c><anno>AbstVersion</anno></c>. <c>no_abstract_code</c> means + that the <c>"Abst"</c> chunk is present, but empty.</p> + </desc> + </datatype> + <datatype> + <name name="forms"/> + </datatype> + <datatype> + <name name="compinfo_entry"/> + </datatype> + <datatype> + <name name="attrib_entry"/> + </datatype> + <datatype> + <name name="labeled_entry"/> + </datatype> + <datatype> + <name name="index"/> + </datatype> + <datatype> + <name name="label"/> + </datatype> + <datatype> + <name name="chunkref"/> + </datatype> + <datatype> + <name name="chunkname"/> + </datatype> + <datatype> + <name name="chnk_rsn"/> + </datatype> + <datatype> + <name name="info_rsn"/> + </datatype> + </datatypes> -chunkname() = abstract_code | attributes | compile_info - | exports | labeled_exports - | imports | indexed_imports - | locals | labeled_locals - | atoms - -chunkref() = chunkname() | chunkid()</code> - </section> <funcs> <func> - <name>chunks(Beam, [ChunkRef]) -> {ok, {Module, [ChunkData]}} | {error, beam_lib, Reason}</name> + <name name="chunks" arity="2"/> <fsummary>Read selected chunks from a BEAM file or binary</fsummary> - <type> - <v>Beam = beam()</v> - <v>ChunkRef = chunkref()</v> - <v>Module = atom()</v> - <v>ChunkData = chunkdata()</v> - <v>Reason = {unknown_chunk, Filename, atom()}</v> - <v> | {key_missing_or_invalid, Filename, abstract_code}</v> - <v> | Reason1 -- see info/1</v> - <v> Filename = string()</v> - </type> <desc> <p>Reads chunk data for selected chunks refs. The order of the returned list of chunk data is determined by the order @@ -225,43 +232,26 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>chunks(Beam, [ChunkRef], [Option]) -> {ok, {Module, [ChunkResult]}} | {error, beam_lib, Reason}</name> + <name name="chunks" arity="3"/> <fsummary>Read selected chunks from a BEAM file or binary</fsummary> - <type> - <v>Beam = beam()</v> - <v>ChunkRef = chunkref()</v> - <v>Module = atom()</v> - <v>Option = allow_missing_chunks</v> - <v>ChunkResult = {chunkref(), ChunkContents} | {chunkref(), missing_chunk}</v> - <v>Reason = {missing_chunk, Filename, atom()}</v> - <v> | {key_missing_or_invalid, Filename, abstract_code}</v> - <v> | Reason1 -- see info/1</v> - <v> Filename = string()</v> - </type> <desc> <p>Reads chunk data for selected chunks refs. The order of the returned list of chunk data is determined by the order of the list of chunks references.</p> - <p>By default, if any requested chunk is missing in <c>Beam</c>, + <p>By default, if any requested chunk is missing in <c><anno>Beam</anno></c>, an <c>error</c> tuple is returned. However, if the option <c>allow_missing_chunks</c> has been given, a result will be returned even if chunks are missing. In the result list, any missing chunks will be represented as - <c>{ChunkRef,missing_chunk}</c>. + <c>{<anno>ChunkRef</anno>,missing_chunk}</c>. Note, however, that if the <c>"Atom"</c> chunk if missing, that is considered a fatal error and the return value will be an <c>error</c> tuple.</p> </desc> </func> <func> - <name>version(Beam) -> {ok, {Module, [Version]}} | {error, beam_lib, Reason}</name> + <name name="version" arity="1"/> <fsummary>Read the BEAM file's module version</fsummary> - <type> - <v>Beam = beam()</v> - <v>Module = atom()</v> - <v>Version = term()</v> - <v>Reason -- see chunks/2</v> - </type> <desc> <p>Returns the module version(s). A version is defined by the module attribute <c>-vsn(Vsn)</c>. If this attribute is @@ -282,51 +272,30 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>md5(Beam) -> {ok, {Module, MD5}} | {error, beam_lib, Reason}</name> + <name name="md5" arity="1"/> <fsummary>Read the BEAM file's module version</fsummary> - <type> - <v>Beam = beam()</v> - <v>Module = atom()</v> - <v>MD5 = binary()</v> - <v>Reason -- see chunks/2</v> - </type> <desc> <p>Calculates an MD5 redundancy check for the code of the module (compilation date and other attributes are not included).</p> </desc> </func> <func> - <name>info(Beam) -> [{Item, Info}] | {error, beam_lib, Reason1}</name> + <name name="info" arity="1"/> <fsummary>Information about a BEAM file</fsummary> - <type> - <v>Beam = beam()</v> - <v>Item, Info -- see below</v> - <v>Reason1 = {chunk_too_big, Filename, ChunkId, ChunkSize, FileSize}</v> - <v> | {invalid_beam_file, Filename, Pos}</v> - <v> | {invalid_chunk, Filename, ChunkId}</v> - <v> | {missing_chunk, Filename, ChunkId}</v> - <v> | {not_a_beam_file, Filename}</v> - <v> | {file_error, Filename, Posix}</v> - <v> Filename = string()</v> - <v> ChunkId = chunkid()</v> - <v> ChunkSize = FileSize = int()</v> - <v> Pos = int()</v> - <v> Posix = posix() -- see file(3)</v> - </type> <desc> <p>Returns a list containing some information about a BEAM file as tuples <c>{Item, Info}</c>:</p> <taglist> - <tag><c>{file, Filename} | {binary, Binary}</c></tag> + <tag><c>{file, <anno>Filename</anno>} | {binary, <anno>Binary</anno>}</c></tag> <item> <p>The name (string) of the BEAM file, or the binary from which the information was extracted.</p> </item> - <tag><c>{module, Module}</c></tag> + <tag><c>{module, <anno>Module</anno>}</c></tag> <item> <p>The name (atom) of the module.</p> </item> - <tag><c>{chunks, [{ChunkId, Pos, Size}]}</c></tag> + <tag><c>{chunks, [{<anno>ChunkId</anno>, <anno>Pos</anno>, <anno>Size</anno>}]}</c></tag> <item> <p>For each chunk, the identifier (string) and the position and size of the chunk data, in bytes.</p> @@ -335,17 +304,9 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>cmp(Beam1, Beam2) -> ok | {error, beam_lib, Reason}</name> + <name name="cmp" arity="2"/> <fsummary>Compare two BEAM files</fsummary> - <type> - <v>Beam1 = Beam2 = beam()</v> - <v>Reason = {modules_different, Module1, Module2}</v> - <v> | {chunks_different, ChunkId}</v> - <v> | different_chunks</v> - <v> | Reason1 -- see info/1</v> - <v> Module1 = Module2 = atom()</v> - <v> ChunkId = chunkid()</v> - </type> + <type name="cmp_rsn"/> <desc> <p>Compares the contents of two BEAM files. If the module names are the same, and all chunks except for the <c>"CInf"</c> chunk @@ -356,34 +317,23 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>cmp_dirs(Dir1, Dir2) -> {Only1, Only2, Different} | {error, beam_lib, Reason1}</name> + <name name="cmp_dirs" arity="2"/> <fsummary>Compare the BEAM files in two directories</fsummary> - <type> - <v>Dir1 = Dir2 = string() | atom()</v> - <v>Different = [{Filename1, Filename2}]</v> - <v>Only1 = Only2 = [Filename]</v> - <v>Filename = Filename1 = Filename2 = string()</v> - <v>Reason1 = {not_a_directory, term()} | -- see info/1</v> - </type> <desc> <p>The <c>cmp_dirs/2</c> function compares the BEAM files in two directories. Only files with extension <c>".beam"</c> are - compared. BEAM files that exist in directory <c>Dir1</c> - (<c>Dir2</c>) only are returned in <c>Only1</c> - (<c>Only2</c>). BEAM files that exist on both directories but + compared. BEAM files that exist in directory <c><anno>Dir1</anno></c> + (<c><anno>Dir2</anno></c>) only are returned in <c><anno>Only1</anno></c> + (<c><anno>Only2</anno></c>). BEAM files that exist on both directories but are considered different by <c>cmp/2</c> are returned as - pairs {<c>Filename1</c>, <c>Filename2</c>} where - <c>Filename1</c> (<c>Filename2</c>) exists in directory - <c>Dir1</c> (<c>Dir2</c>).</p> + pairs {<c><anno>Filename1</anno></c>, <c><anno>Filename2</anno></c>} where + <c><anno>Filename1</anno></c> (<c><anno>Filename2</anno></c>) exists in directory + <c><anno>Dir1</anno></c> (<c><anno>Dir2</anno></c>).</p> </desc> </func> <func> - <name>diff_dirs(Dir1, Dir2) -> ok | {error, beam_lib, Reason1}</name> + <name name="diff_dirs" arity="2"/> <fsummary>Compare the BEAM files in two directories</fsummary> - <type> - <v>Dir1 = Dir2 = string() | atom()</v> - <v>Reason1 = {not_a_directory, term()} | -- see info/1</v> - </type> <desc> <p>The <c>diff_dirs/2</c> function compares the BEAM files in two directories the way <c>cmp_dirs/2</c> does, but names of @@ -392,13 +342,8 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>strip(Beam1) -> {ok, {Module, Beam2}} | {error, beam_lib, Reason1}</name> + <name name="strip" arity="1"/> <fsummary>Removes chunks not needed by the loader from a BEAM file</fsummary> - <type> - <v>Beam1 = Beam2 = beam()</v> - <v>Module = atom()</v> - <v>Reason1 -- see info/1</v> - </type> <desc> <p>The <c>strip/1</c> function removes all chunks from a BEAM file except those needed by the loader. In particular, @@ -406,15 +351,8 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>strip_files(Files) -> {ok, [{Module, Beam2}]} | {error, beam_lib, Reason1}</name> + <name name="strip_files" arity="1"/> <fsummary>Removes chunks not needed by the loader from BEAM files</fsummary> - <type> - <v>Files = [Beam1]</v> - <v> Beam1 = beam()</v> - <v>Module = atom()</v> - <v>Beam2 = beam()</v> - <v>Reason1 -- see info/1</v> - </type> <desc> <p>The <c>strip_files/1</c> function removes all chunks except those needed by the loader from BEAM files. In particular, @@ -424,30 +362,20 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>strip_release(Dir) -> {ok, [{Module, Filename]}} | {error, beam_lib, Reason1}</name> + <name name="strip_release" arity="1"/> <fsummary>Removes chunks not needed by the loader from all BEAM files of a release</fsummary> - <type> - <v>Dir = string() | atom()</v> - <v>Module = atom()</v> - <v>Filename = string()</v> - <v>Reason1 = {not_a_directory, term()} | -- see info/1</v> - </type> <desc> <p>The <c>strip_release/1</c> function removes all chunks except those needed by the loader from the BEAM files of a - release. <c>Dir</c> should be the installation root + release. <c><anno>Dir</anno></c> should be the installation root directory. For example, the current OTP release can be stripped with the call <c>beam_lib:strip_release(code:root_dir())</c>.</p> </desc> </func> <func> - <name>format_error(Reason) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Return an English description of a BEAM read error reply</fsummary> - <type> - <v>Reason -- see other functions</v> - <v>Chars = [char() | Chars]</v> - </type> <desc> <p>Given the error returned by any function in this module, the function <c>format_error</c> returns a descriptive string @@ -456,12 +384,11 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>crypto_key_fun(CryptoKeyFun) -> ok | {error, Reason}</name> + <name name="crypto_key_fun" arity="1"/> <fsummary>Register a fun that provides a crypto key</fsummary> - <type> - <v>CryptoKeyFun = fun() -- see below</v> - <v>Reason = badfun | exists | term()</v> - </type> + <type name="crypto_fun"/> + <type name="crypto_fun_arg"/> + <type name="mode"/> <desc> <p>The <c>crypto_key_fun/1</c> function registers a unary fun that will be called if <c>beam_lib</c> needs to read an @@ -495,11 +422,8 @@ chunkref() = chunkname() | chunkid()</code> </desc> </func> <func> - <name>clear_crypto_key_fun() -> {ok, Result}</name> + <name name="clear_crypto_key_fun" arity="0"/> <fsummary>Unregister the current crypto key fun</fsummary> - <type> - <v>Result = undefined | term()</v> - </type> <desc> <p>Unregisters the crypto key fun and terminates the process holding it, started by <c>crypto_key_fun/1</c>.</p> diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index c81023862e..88ce77e0d0 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2009</year> - <year>2010</year> + <year>2011</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -53,37 +53,35 @@ module. </p> </note> - - </description> - <section> - <title>DATA TYPES</title> - <code type="none"> - cp() - - Opaque data-type representing a compiled search-pattern. Guaranteed to be a tuple() - to allow programs to distinguish it from non precompiled search patterns. - </code> - <code type="none"> - part() = {Start,Length} - Start = int() - Length = int() - - A representaion of a part (or range) in a binary. Start is a + <datatypes> + <datatype> + <name name="cp"/> + <desc><p>Opaque data-type representing a compiled + search-pattern. Guaranteed to be a tuple() to allow programs to + distinguish it from non precompiled search patterns.</p> + </desc> + </datatype> + <datatype> + <name name="part"/> + <desc><p>A representaion of a part (or range) in a binary. Start is a zero-based offset into a binary() and Length is the length of that part. As input to functions in this module, a reverse part specification is allowed, constructed with a negative Length, so that the part of the binary begins at Start + Length and is -Length long. This is useful for referencing the last N bytes of a binary as {size(Binary), -N}. The functions - in this module always return part()'s with positive Length. - </code> - </section> + in this module always return part()'s with positive Length.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>at(Subject, Pos) -> int()</name> + <name>at(Subject, Pos) -> byte()</name> <fsummary>Returns the byte at a specific position in a binary</fsummary> <type> <v>Subject = binary()</v> - <v>Pos = int() >= 0</v> + <v>Pos = integer() >= 0</v> </type> <desc> @@ -95,7 +93,7 @@ </desc> </func> <func> - <name>bin_to_list(Subject) -> list()</name> + <name>bin_to_list(Subject) -> [byte()]</name> <fsummary>Convert a binary to a list of integers</fsummary> <type> <v>Subject = binary()</v> @@ -105,7 +103,7 @@ </desc> </func> <func> - <name>bin_to_list(Subject, PosLen) -> list()</name> + <name>bin_to_list(Subject, PosLen) -> [byte()]</name> <fsummary>Convert a binary to a list of integers</fsummary> <type> <v>Subject = binary()</v> @@ -113,7 +111,7 @@ </type> <desc> - <p>Converts <c>Subject</c> to a list of <c>int()</c>s, each representing + <p>Converts <c>Subject</c> to a list of <c>byte()</c>s, each representing the value of one byte. The <c>part()</c> denotes which part of the <c>binary()</c> to convert. Example:</p> @@ -126,12 +124,12 @@ </desc> </func> <func> - <name>bin_to_list(Subject, Pos, Len) -> list()</name> + <name>bin_to_list(Subject, Pos, Len) -> [byte()]</name> <fsummary>Convert a binary to a list of integers</fsummary> <type> <v>Subject = binary()</v> - <v>Pos = int()</v> - <v>Len = int()</v> + <v>Pos = integer() >= 0</v> + <v>Len = integer() >= 0</v> </type> <desc> <p>The same as<c> bin_to_list(Subject,{Pos,Len})</c>.</p> @@ -185,7 +183,7 @@ <fsummary>Duplicates a binary N times and creates a new</fsummary> <type> <v>Subject = binary()</v> - <v>N = int() >= 0</v> + <v>N = integer() >= 0</v> </type> <desc> <p>Creates a binary with the content of <c>Subject</c> duplicated <c>N</c> times.</p> @@ -211,7 +209,7 @@ <fsummary>Decode a whole binary into an integer of arbitrary size</fsummary> <type> <v>Subject = binary()</v> - <v>Unsigned = int() >= 0</v> + <v>Unsigned = integer() >= 0</v> </type> <desc> <p>The same as <c>decode_unsigned(Subject,big)</c>.</p> @@ -223,12 +221,12 @@ <type> <v>Subject = binary()</v> <v>Endianess = big | little</v> - <v>Unsigned = int() >= 0</v> + <v>Unsigned = integer() >= 0</v> </type> <desc> <p>Converts the binary digit representation, in big or little - endian, of a positive integer in <c>Subject</c> to an Erlang <c>int()</c>.</p> + endian, of a positive integer in <c>Subject</c> to an Erlang <c>integer()</c>.</p> <p>Example:</p> @@ -242,7 +240,7 @@ <name>encode_unsigned(Unsigned) -> binary()</name> <fsummary>Encodes an unsigned integer into the minimal binary</fsummary> <type> - <v>Unsigned = int() >= 0</v> + <v>Unsigned = integer() >= 0</v> </type> <desc> <p>The same as <c>encode_unsigned(Unsigned,big)</c>.</p> @@ -252,7 +250,7 @@ <name>encode_unsigned(Unsigned,Endianess) -> binary()</name> <fsummary>Encodes an unsigned integer into the minimal binary</fsummary> <type> - <v>Unsigned = int() >= 0</v> + <v>Unsigned = integer() >= 0</v> <v>Endianess = big | little</v> </type> <desc> @@ -270,7 +268,7 @@ </desc> </func> <func> - <name>first(Subject) -> int()</name> + <name>first(Subject) -> byte()</name> <fsummary>Returns the first byte of a binary</fsummary> <type> <v>Subject = binary()</v> @@ -283,7 +281,7 @@ </desc> </func> <func> - <name>last(Subject) -> int()</name> + <name>last(Subject) -> byte()</name> <fsummary>Returns the last byte of a binary</fsummary> <type> <v>Subject = binary()</v> @@ -306,7 +304,7 @@ </desc> </func> <func> - <name>longest_common_prefix(Binaries) -> int()</name> + <name>longest_common_prefix(Binaries) -> integer() >= 0</name> <fsummary>Returns length of longest common prefix for a set of binaries</fsummary> <type> <v>Binaries = [ binary() ]</v> @@ -327,7 +325,7 @@ </desc> </func> <func> - <name>longest_common_suffix(Binaries) -> int()</name> + <name>longest_common_suffix(Binaries) -> integer() >= 0</name> <fsummary>Returns length of longest common suffix for a set of binaries</fsummary> <type> <v>Binaries = [ binary() ]</v> @@ -450,7 +448,7 @@ [{1,4}] </code> - <p>The result shows that <<bcde">> is selected instead of the + <p>The result shows that <<"bcde">> is selected instead of the shorter match <<"bc">> (which would have given raise to one more match,<<"de">>). This corresponds to the behavior of posix regular expressions (and programs like awk), but is not @@ -506,15 +504,15 @@ <fsummary>Extracts a part of a binary</fsummary> <type> <v>Subject = binary()</v> - <v>Pos = int()</v> - <v>Len = int()</v> + <v>Pos = integer() >= 0</v> + <v>Len = integer() >= 0</v> </type> <desc> <p>The same as <c>part(Subject, {Pos, Len})</c>.</p> </desc> </func> <func> - <name>referenced_byte_size(binary()) -> int()</name> + <name>referenced_byte_size(binary()) -> integer() >= 0</name> <fsummary>Determines the size of the actual binary pointed out by a sub-binary</fsummary> <desc> @@ -581,42 +579,28 @@ store(Binary, GBSet) -> </desc> </func> <func> - <name>replace(Subject,Pattern,Replacement) -> Result</name> + <name name="replace" arity="3"/> <fsummary>Replaces bytes in a binary according to a pattern</fsummary> - <type> - <v>Subject = binary()</v> - <v>Pattern = binary() | [ binary() ] | cp()</v> - <v>Replacement = binary()</v> - <v>Result = binary()</v> - </type> <desc> - <p>The same as <c>replace(Subject,Pattern,Replacement,[])</c>.</p> + <p>The same as <c>replace(<anno>Subject</anno>,<anno>Pattern</anno>,<anno>Replacement</anno>,[])</c>.</p> </desc> </func> <func> - <name>replace(Subject,Pattern,Replacement,Options) -> Result</name> + <name name="replace" arity="4"/> <fsummary>Replaces bytes in a binary according to a pattern</fsummary> - <type> - <v>Subject = binary()</v> - <v>Pattern = binary() | [ binary() ] | cp()</v> - <v>Replacement = binary()</v> - <v>Result = binary()</v> - <v>Options = [ Option ]</v> - <v>Option = global | {scope, part()} | {insert_replaced, InsPos}</v> - <v>InsPos = OnePos | [ OnePos ]</v> - <v>OnePos = int() =< byte_size(Replacement)</v> - </type> + <type_desc variable="OnePos">An integer() =< byte_size(<anno>Replacement</anno>) + </type_desc> <desc> <p>Constructs a new binary by replacing the parts in - <c>Subject</c> matching <c>Pattern</c> with the content of - <c>Replacement</c>.</p> + <c><anno>Subject</anno></c> matching <c><anno>Pattern</anno></c> with the content of + <c><anno>Replacement</anno></c>.</p> - <p>If the matching sub-part of <c>Subject</c> giving raise to the + <p>If the matching sub-part of <c><anno>Subject</anno></c> giving raise to the replacement is to be inserted in the result, the option - <c>{insert_replaced, InsPos}</c> will insert the matching part into - <c>Replacement</c> at the given position (or positions) before actually - inserting <c>Replacement</c> into the <c>Subject</c>. Example:</p> + <c>{insert_replaced, <anno>InsPos</anno>}</c> will insert the matching part into + <c><anno>Replacement</anno></c> at the given position (or positions) before actually + inserting <c><anno>Replacement</anno></c> into the <c><anno>Subject</anno></c>. Example:</p> <code> 1> binary:replace(<<"abcde">>,<<"b">>,<<"[]">>,[{insert_replaced,1}]). @@ -632,42 +616,30 @@ store(Binary, GBSet) -> <<"a[b-b]c[d-d]e">> </code> - <p>If any position given in <c>InsPos</c> is greater than the size of the replacement binary, a <c>badarg</c> exception is raised.</p> + <p>If any position given in <c><anno>InsPos</anno></c> is greater than the size of the replacement binary, a <c>badarg</c> exception is raised.</p> <p>The options <c>global</c> and <c>{scope, part()}</c> work as for <seealso marker="#split-3">split/3</seealso>. The return type is always a <c>binary()</c>.</p> - <p>For a description of <c>Pattern</c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p> + <p>For a description of <c><anno>Pattern</anno></c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p> </desc> </func> <func> - <name>split(Subject,Pattern) -> Parts</name> + <name name="split" arity="2"/> <fsummary>Splits a binary according to a pattern</fsummary> - <type> - <v>Subject = binary()</v> - <v>Pattern = binary() | [ binary() ] | cp()</v> - <v>Parts = [ binary() ]</v> - </type> <desc> - <p>The same as <c>split(Subject, Pattern, [])</c>.</p> + <p>The same as <c>split(<anno>Subject</anno>, <anno>Pattern</anno>, [])</c>.</p> </desc> </func> <func> - <name>split(Subject,Pattern,Options) -> Parts</name> + <name name="split" arity="3"/> <fsummary>Splits a binary according to a pattern</fsummary> - <type> - <v>Subject = binary()</v> - <v>Pattern = binary() | [ binary() ] | cp()</v> - <v>Parts = [ binary() ]</v> - <v>Options = [ Option ]</v> - <v>Option = {scope, part()} | trim | global</v> - </type> <desc> - <p>Splits Binary into a list of binaries based on Pattern. If + <p>Splits <c><anno>Subject</anno></c> into a list of binaries based on <c><anno>Pattern</anno></c>. If the option global is not given, only the first occurrence of - Pattern in Subject will give rise to a split.</p> + <c><anno>Pattern</anno></c> in <c><anno>Subject</anno></c> will give rise to a split.</p> - <p>The parts of Pattern actually found in Subject are not included in the result.</p> + <p>The parts of <c><anno>Pattern</anno></c> actually found in <c><anno>Subject</anno></c> are not included in the result.</p> <p>Example:</p> @@ -696,7 +668,7 @@ store(Binary, GBSet) -> <tag>global</tag> - <item><p>Repeats the split until the <c>Subject</c> is + <item><p>Repeats the split until the <c><anno>Subject</anno></c> is exhausted. Conceptually the global option makes split work on the positions returned by <seealso marker="#matches-3">matches/3</seealso>, while it normally @@ -716,12 +688,12 @@ store(Binary, GBSet) -> </code> <p>The return type is always a list of binaries that are all - referencing <c>Subject</c>. This means that the data in <c>Subject</c> is not - actually copied to new binaries and that <c>Subject</c> cannot be + referencing <c><anno>Subject</anno></c>. This means that the data in <c><anno>Subject</anno></c> is not + actually copied to new binaries and that <c><anno>Subject</anno></c> cannot be garbage collected until the results of the split are no longer referenced.</p> - <p>For a description of <c>Pattern</c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p> + <p>For a description of <c><anno>Pattern</anno></c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml index 19e3ac1f08..ddae388a1b 100644 --- a/lib/stdlib/doc/src/c.xml +++ b/lib/stdlib/doc/src/c.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -39,43 +39,33 @@ </description> <funcs> <func> - <name>bt(Pid) -> void()</name> + <name name="bt" arity="1"/> <fsummary>Stack backtrace for a process</fsummary> - <type> - <v>Pid = pid()</v> - </type> <desc> <p>Stack backtrace for a process. Equivalent to - <c>erlang:process_display(Pid, backtrace)</c>.</p> + <c>erlang:process_display(<anno>Pid</anno>, backtrace)</c>.</p> </desc> </func> <func> - <name>c(File) -> {ok, Module} | error</name> - <name>c(File, Options) -> {ok, Module} | error</name> + <name name="c" arity="1"/> + <name name="c" arity="2"/> <fsummary>Compile and load code in a file</fsummary> - <type> - <v>File = name() -- see filename(3)</v> - <v>Options = [Opt] -- see compile:file/2</v> - </type> <desc> <p><c>c/1,2</c> compiles and then purges and loads the code for - a file. <c>Options</c> defaults to []. Compilation is + a file. <c><anno>Options</anno></c> defaults to []. Compilation is equivalent to:</p> <code type="none"> -compile:file(File, Options ++ [report_errors, report_warnings])</code> +compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_warnings])</code> <p>Note that purging the code means that any processes lingering in old code for the module are killed without warning. See <c>code/3</c> for more information.</p> </desc> </func> <func> - <name>cd(Dir) -> void()</name> + <name name="cd" arity="1"/> <fsummary>Change working directory</fsummary> - <type> - <v>Dir = name() -- see filename(3)</v> - </type> <desc> - <p>Changes working directory to <c>Dir</c>, which may be a + <p>Changes working directory to <c><anno>Dir</anno></c>, which may be a relative name, and then prints the name of the new working directory.</p> <pre> @@ -84,14 +74,14 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>flush() -> void()</name> + <name name="flush" arity="0"/> <fsummary>Flush any messages sent to the shell</fsummary> <desc> <p>Flushes any messages sent to the shell.</p> </desc> </func> <func> - <name>help() -> void()</name> + <name name="help" arity="0"/> <fsummary>Help information</fsummary> <desc> <p>Displays help information: all valid shell internal commands, @@ -99,8 +89,8 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>i() -> void()</name> - <name>ni() -> void()</name> + <name name="i" arity="0"/> + <name name="ni" arity="0"/> <fsummary>Information about the system</fsummary> <desc> <p><c>i/0</c> displays information about the system, listing @@ -109,26 +99,20 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>i(X, Y, Z) -> void()</name> + <name name="i" arity="3"/> <fsummary>Information about pid <X.Y.Z></fsummary> - <type> - <v>X = Y = Z = int()</v> - </type> <desc> <p>Displays information about a process, Equivalent to - <c>process_info(pid(X, Y, Z))</c>, but location transparent.</p> + <c>process_info(pid(<anno>X</anno>, <anno>Y</anno>, <anno>Z</anno>))</c>, but location transparent.</p> </desc> </func> <func> - <name>l(Module) -> void()</name> + <name name="l" arity="1"/> <fsummary>Load or reload module</fsummary> - <type> - <v>Module = atom()</v> - </type> <desc> <p>Purges and loads, or reloads, a module by calling - <c>code:purge(Module)</c> followed by - <c>code:load_file(Module)</c>.</p> + <c>code:purge(<anno>Module</anno>)</c> followed by + <c>code:load_file(<anno>Module</anno>)</c>.</p> <p>Note that purging the code means that any processes lingering in old code for the module are killed without warning. See <c>code/3</c> for more information.</p> @@ -136,35 +120,33 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code> </func> <func> <name>lc(Files) -> ok</name> - <fsummary>Compile a list of files</fsummary> <type> <v>Files = [File]</v> - <v> File = name() -- see filename(3)</v> + <v>File = <seealso marker="file#type-filename">file:filename() + </seealso></v> </type> + <fsummary>Compile a list of files</fsummary> <desc> <p>Compiles a list of files by calling <c>compile:file(File, [report_errors, report_warnings])</c> for each <c>File</c> in <c>Files</c>.</p> </desc> </func> <func> - <name>ls() -> void()</name> + <name name="ls" arity="0"/> <fsummary>List files in the current directory</fsummary> <desc> <p>Lists files in the current directory.</p> </desc> </func> <func> - <name>ls(Dir) -> void()</name> + <name name="ls" arity="1"/> <fsummary>List files in a directory</fsummary> - <type> - <v>Dir = name() -- see filename(3)</v> - </type> <desc> - <p>Lists files in directory <c>Dir</c>.</p> + <p>Lists files in directory <c><anno>Dir</anno></c>.</p> </desc> </func> <func> - <name>m() -> void()</name> + <name name="m" arity="0"/> <fsummary>Which modules are loaded</fsummary> <desc> <p>Displays information about the loaded modules, including @@ -172,84 +154,67 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>m(Module) -> void()</name> + <name name="m" arity="1"/> <fsummary>Information about a module</fsummary> - <type> - <v>Module = atom()</v> - </type> <desc> - <p>Displays information about <c>Module</c>.</p> + <p>Displays information about <c><anno>Module</anno></c>.</p> </desc> </func> <func> - <name>memory() -> [{Type, Size}]</name> + <name name="memory" arity="0"/> <fsummary>Memory allocation information</fsummary> - <type> - <v>Type, Size -- see erlang:memory/0</v> - </type> <desc> <p>Memory allocation information. Equivalent to - <c>erlang:memory/0</c>.</p> + <seealso marker="erts:erlang#memory/0"><c>erlang:memory/0</c> + </seealso>.</p> </desc> </func> <func> - <name>memory(Type) -> Size</name> - <name>memory([Type]) -> [{Type, Size}]</name> + <name name="memory" arity="1" clause_i="1"/> + <name name="memory" arity="1" clause_i="2"/> <fsummary>Memory allocation information</fsummary> - <type> - <v>Type, Size -- see erlang:memory/0</v> - </type> <desc> <p>Memory allocation information. Equivalent to - <c>erlang:memory/1</c>.</p> + <seealso marker="erts:erlang#memory/1"><c>erlang:memory/1</c> + </seealso>.</p> </desc> </func> <func> - <name>nc(File) -> {ok, Module} | error</name> - <name>nc(File, Options) -> {ok, Module} | error</name> + <name name="nc" arity="1"/> + <name name="nc" arity="2"/> <fsummary>Compile and load code in a file on all nodes</fsummary> - <type> - <v>File = name() -- see filename(3)</v> - <v>Options = [Opt] -- see compile:file/2</v> - </type> <desc> <p>Compiles and then loads the code for a file on all nodes. - <c>Options</c> defaults to []. Compilation is equivalent to:</p> + <c><anno>Options</anno></c> defaults to []. Compilation is equivalent to:</p> <code type="none"> -compile:file(File, Opts ++ [report_errors, report_warnings])</code> +compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>nl(Module) -> void()</name> + <name name="nl" arity="1"/> <fsummary>Load module on all nodes</fsummary> - <type> - <v>Module = atom()</v> - </type> <desc> - <p>Loads <c>Module</c> on all nodes.</p> + <p>Loads <c><anno>Module</anno></c> on all nodes.</p> </desc> </func> <func> - <name>pid(X, Y, Z) -> pid()</name> + <name name="pid" arity="3"/> <fsummary>Convert X,Y,Z to a pid</fsummary> - <type> - <v>X = Y = Z = int()</v> - </type> <desc> - <p>Converts <c>X</c>, <c>Y</c>, <c>Z</c> to the pid + <p>Converts <c><anno>X</anno></c>, <c><anno>Y</anno></c>, <c><anno>Z</anno></c> to the pid <c><![CDATA[<X.Y.Z>]]></c>. This function should only be used when debugging.</p> </desc> </func> <func> - <name>pwd() -> void()</name> + <name name="pwd" arity="0"/> <fsummary>Print working directory</fsummary> <desc> <p>Prints the name of the working directory.</p> </desc> </func> <func> - <name>q() -> void()</name> + <name name="q" arity="0"/> <fsummary>Quit - shorthand for <c>init:stop()</c></fsummary> <desc> <p>This function is shorthand for <c>init:stop()</c>, that is, @@ -257,8 +222,8 @@ compile:file(File, Opts ++ [report_errors, report_warnings])</code> </desc> </func> <func> - <name>regs() -> void()</name> - <name>nregs() -> void()</name> + <name name="regs" arity="0"/> + <name name="nregs" arity="0"/> <fsummary>Information about registered processes</fsummary> <desc> <p><c>regs/0</c> displays information about all registered diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml index 075c7f9c78..f8db48e00c 100644 --- a/lib/stdlib/doc/src/calendar.xml +++ b/lib/stdlib/doc/src/calendar.xml @@ -73,100 +73,120 @@ week number.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -date() = {Year, Month, Day} - Year = int() - Month = 1..12 - Day = 1..31 -Year cannot be abbreviated. Example: 93 denotes year 93, not 1993. -Valid range depends on the underlying OS. -The date tuple must denote a valid date. + <datatypes> + <datatype> + <name name="datetime"/> + </datatype> + <datatype> + <name name="datetime1970"/> + </datatype> + <datatype> + <name name="date"/> + </datatype> + <datatype> + <name name="year"/> + <desc><p>Year cannot be abbreviated. Example: 93 denotes year + 93, not 1993. Valid range depends on the underlying OS. The + date tuple must denote a valid date.</p> + </desc> + </datatype> + <datatype> + <name name="year1970"/> + </datatype> + <datatype> + <name name="month"/> + </datatype> + <datatype> + <name name="day"/> + </datatype> + <datatype> + <name name="time"/> + </datatype> + <datatype> + <name name="hour"/> + </datatype> + <datatype> + <name name="minute"/> + </datatype> + <datatype> + <name name="second"/> + </datatype> + <datatype> + <name name="daynum"/> + </datatype> + <datatype> + <name name="ldom"/> + </datatype> + <datatype> + <name name="yearweeknum"/> + </datatype> + <datatype> + <name name="weeknum"/> + </datatype> + </datatypes> -time() = {Hour, Minute, Second} - Hour = 0..23 - Minute = Second = 0..59</code> - </section> <funcs> <func> - <name>date_to_gregorian_days(Date) -> Days</name> - <name>date_to_gregorian_days(Year, Month, Day) -> Days</name> + <name name="date_to_gregorian_days" arity="1"/> + <name name="date_to_gregorian_days" arity="3"/> + <type variable="Date" name_i="1"/> + <type variable="Year"/> + <type variable="Month"/> + <type variable="Day"/> <fsummary>Compute the number of days from year 0 up to the given date</fsummary> - <type> - <v>Date = date()</v> - <v>Days = int()</v> - </type> <desc> <p>This function computes the number of gregorian days starting with year 0 and ending at the given date.</p> </desc> </func> <func> - <name>datetime_to_gregorian_seconds({Date, Time}) -> Seconds</name> + <name name="datetime_to_gregorian_seconds" arity="1"/> <fsummary>Compute the number of seconds from year 0 up to the given date and time</fsummary> - <type> - <v>Date = date()</v> - <v>Time = time()</v> - <v>Seconds = int()</v> - </type> <desc> <p>This function computes the number of gregorian seconds starting with year 0 and ending at the given date and time.</p> </desc> </func> <func> - <name>day_of_the_week(Date) -> DayNumber</name> - <name>day_of_the_week(Year, Month, Day) -> DayNumber</name> + <name name="day_of_the_week" arity="1"/> + <name name="day_of_the_week" arity="3"/> <fsummary>Compute the day of the week</fsummary> - <type> - <v>Date = date()</v> - <v>DayNumber = 1..7</v> - </type> + <type variable="Date" name_i="1"/> + <type variable="Year"/> + <type variable="Month"/> + <type variable="Day"/> <desc> - <p>This function computes the day of the week given <c>Year</c>, - <c>Month</c> and <c>Day</c>. The return value denotes the day + <p>This function computes the day of the week given <c><anno>Year</anno></c>, + <c><anno>Month</anno></c> and <c><anno>Day</anno></c>. The return value denotes the day of the week as <c>1</c>: Monday, <c>2</c>: Tuesday, and so on.</p> </desc> </func> <func> - <name>gregorian_days_to_date(Days) -> Date</name> + <name name="gregorian_days_to_date" arity="1"/> <fsummary>Compute the date given the number of gregorian days</fsummary> - <type> - <v>Days = int()</v> - <v>Date = date()</v> - </type> <desc> <p>This function computes the date given the number of gregorian days.</p> </desc> </func> <func> - <name>gregorian_seconds_to_datetime(Seconds) -> {Date, Time}</name> + <name name="gregorian_seconds_to_datetime" arity="1"/> <fsummary>Compute the date given the number of gregorian days</fsummary> - <type> - <v>Seconds = int()</v> - <v>Date = date()</v> - <v>Time = time()</v> - </type> <desc> <p>This function computes the date and time from the given number of gregorian seconds.</p> </desc> </func> <func> - <name>is_leap_year(Year) -> bool()</name> + <name name="is_leap_year" arity="1"/> <fsummary>Check if a year is a leap year</fsummary> <desc> <p>This function checks if a year is a leap year.</p> </desc> </func> <func> - <name>iso_week_number() -> IsoWeekNumber</name> + <name name="iso_week_number" arity="0"/> <fsummary>Compute the iso week number for the actual date</fsummary> - <type> - <v>IsoWeekNumber = {int(), int()}</v> - </type> <desc> <p>This function returns the tuple {Year, WeekNum} representing the iso week number for the actual date. For determining the @@ -174,42 +194,34 @@ time() = {Hour, Minute, Second} </desc> </func> <func> - <name>iso_week_number(Date) -> IsoWeekNumber</name> + <name name="iso_week_number" arity="1"/> <fsummary>Compute the iso week number for the given date</fsummary> - <type> - <v>Date = date()</v> - <v>IsoWeekNumber = {int(), int()}</v> - </type> <desc> <p>This function returns the tuple {Year, WeekNum} representing the iso week number for the given date.</p> </desc> </func> <func> - <name>last_day_of_the_month(Year, Month) -> int()</name> + <name name="last_day_of_the_month" arity="2"/> <fsummary>Compute the number of days in a month</fsummary> <desc> <p>This function computes the number of days in a month.</p> </desc> </func> <func> - <name>local_time() -> {Date, Time}</name> + <name name="local_time" arity="0"/> <fsummary>Compute local time</fsummary> - <type> - <v>Date = date()</v> - <v>Time = time()</v> - </type> <desc> <p>This function returns the local time reported by the underlying operating system.</p> </desc> </func> <func> - <name>local_time_to_universal_time({Date1, Time1}) -> {Date2, Time2}</name> + <name name="local_time_to_universal_time" arity="1"/> <fsummary>Convert from local time to universal time (deprecated)</fsummary> <desc> <p>This function converts from local time to Universal - Coordinated Time (UTC). <c>Date1</c> must refer to a local + Coordinated Time (UTC). <c><anno>DateTime1</anno></c> must refer to a local date after Jan 1, 1970.</p> <warning> <p>This function is deprecated. Use @@ -222,15 +234,11 @@ time() = {Hour, Minute, Second} </desc> </func> <func> - <name>local_time_to_universal_time_dst({Date1, Time1}) -> [{Date, Time}]</name> + <name name="local_time_to_universal_time_dst" arity="1"/> <fsummary>Convert from local time to universal time(s)</fsummary> - <type> - <v>Date1 = Date = date()</v> - <v>Time1 = Time = time()</v> - </type> <desc> <p>This function converts from local time to Universal - Coordinated Time (UTC). <c>Date1</c> must refer to a local + Coordinated Time (UTC). <c><anno>DateTime1</anno></c> must refer to a local date after Jan 1, 1970.</p> <p>The return value is a list of 0, 1 or 2 possible UTC times:</p> <taglist> @@ -258,65 +266,48 @@ time() = {Hour, Minute, Second} </desc> </func> <func> - <name>now_to_local_time(Now) -> {Date, Time}</name> + <name name="now_to_local_time" arity="1"/> <fsummary>Convert now to local date and time</fsummary> - <type> - <v>Now -- see erlang:now/0</v> - <v>Date = date()</v> - <v>Time = time()</v> - </type> <desc> <p>This function returns local date and time converted from the return value from <c>erlang:now()</c>.</p> </desc> </func> <func> - <name>now_to_universal_time(Now) -> {Date, Time}</name> - <name>now_to_datetime(Now) -> {Date, Time}</name> + <name name="now_to_universal_time" arity="1"/> + <name name="now_to_datetime" arity="1"/> <fsummary>Convert now to date and time</fsummary> - <type> - <v>Now -- see erlang:now/0</v> - <v>Date = date()</v> - <v>Time = time()</v> - </type> <desc> <p>This function returns Universal Coordinated Time (UTC) converted from the return value from <c>erlang:now()</c>.</p> </desc> </func> <func> - <name>seconds_to_daystime(Seconds) -> {Days, Time}</name> + <name name="seconds_to_daystime" arity="1"/> <fsummary>Compute days and time from seconds</fsummary> - <type> - <v>Seconds = Days = int()</v> - <v>Time = time()</v> - </type> <desc> <p>This function transforms a given number of seconds into days, - hours, minutes, and seconds. The <c>Time</c> part is always - non-negative, but <c>Days</c> is negative if the argument - <c>Seconds</c> is.</p> + hours, minutes, and seconds. The <c><anno>Time</anno></c> part is always + non-negative, but <c><anno>Days</anno></c> is negative if the argument + <c><anno>Seconds</anno></c> is.</p> </desc> </func> <func> - <name>seconds_to_time(Seconds) -> Time</name> + <name name="seconds_to_time" arity="1"/> <fsummary>Compute time from seconds</fsummary> - <type> - <v>Seconds = int() < 86400</v> - <v>Time = time()</v> - </type> + <type name="secs_per_day"/> <desc> <p>This function computes the time from the given number of - seconds. <c>Seconds</c> must be less than the number of + seconds. <c><anno>Seconds</anno></c> must be less than the number of seconds per day (86400).</p> </desc> </func> <func> - <name>time_difference(T1, T2) -> {Days, Time}</name> + <name name="time_difference" arity="2"/> <fsummary>Compute the difference between two times (deprecated)</fsummary> <desc> - <p>This function returns the difference between two <c>{Date, Time}</c> tuples. <c>T2</c> should refer to an epoch later - than <c>T1</c>.</p> + <p>This function returns the difference between two <c>{Date, Time}</c> tuples. <c><anno>T2</anno></c> should refer to an epoch later + than <c><anno>T1</anno></c>.</p> <warning> <p>This function is obsolete. Use the conversion functions for gregorian days and seconds instead.</p> @@ -324,24 +315,17 @@ time() = {Hour, Minute, Second} </desc> </func> <func> - <name>time_to_seconds(Time) -> Seconds</name> + <name name="time_to_seconds" arity="1"/> <fsummary>Compute the number of seconds since midnight up to the given time</fsummary> - <type> - <v>Time = time()</v> - <v>Seconds = int()</v> - </type> + <type name="secs_per_day"/> <desc> <p>This function computes the number of seconds since midnight up to the specified time.</p> </desc> </func> <func> - <name>universal_time() -> {Date, Time}</name> + <name name="universal_time" arity="0"/> <fsummary>Compute universal time</fsummary> - <type> - <v>Date = date()</v> - <v>Time = time()</v> - </type> <desc> <p>This function returns the Universal Coordinated Time (UTC) reported by the underlying operating system. Local time is @@ -349,25 +333,22 @@ time() = {Hour, Minute, Second} </desc> </func> <func> - <name>universal_time_to_local_time({Date1, Time1}) -> {Date2, Time2}</name> + <name name="universal_time_to_local_time" arity="1"/> <fsummary>Convert from universal time to local time</fsummary> - <type> - <v>Date1 = Date2 = date()</v> - <v>Time1 = Time2 = time()</v> - </type> <desc> <p>This function converts from Universal Coordinated Time (UTC) - to local time. <c>Date1</c> must refer to a date after Jan 1, + to local time. <c><anno>DateTime</anno></c> must refer to a date after Jan 1, 1970.</p> </desc> </func> <func> - <name>valid_date(Date) -> bool()</name> - <name>valid_date(Year, Month, Day) -> bool()</name> + <name name="valid_date" arity="1"/> + <name name="valid_date" arity="3"/> + <type variable="Date" name_i="1"/> + <type variable="Year"/> + <type variable="Month"/> + <type variable="Day"/> <fsummary>Check if a date is valid</fsummary> - <type> - <v>Date = date()</v> - </type> <desc> <p>This function checks if a date is a valid.</p> </desc> diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml index b002af6616..215ec154ed 100644 --- a/lib/stdlib/doc/src/dets.xml +++ b/lib/stdlib/doc/src/dets.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -100,50 +100,99 @@ the process with the error tuple). If given badly formed arguments, all functions exit the process with a <c>badarg</c> message.</p> - <p><em>Types</em></p> - <pre> -access() = read | read_write -auto_save() = infinity | int() -bindings_cont() = tuple() -bool() = true | false -file() = string() -int() = integer() >= 0 -keypos() = integer() >= 1 -name() = atom() | reference() -no_slots() = integer() >= 0 | default -object() = tuple() -object_cont() = tuple() -select_cont() = tuple() -type() = bag | duplicate_bag | set -version() = 8 | 9 | default </pre> </description> + <datatypes> + <datatype> + <name name="access"/> + </datatype> + <datatype> + <name name="auto_save"/> + </datatype> + <datatype> + <name name="bindings_cont"/> + <desc> + <p>Opaque continuation used by <seealso marker="#match/1"> + <c>match/1</c></seealso> and <seealso marker="#match/3"> + <c>match/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="cont"/> + <desc> + <p>Opaque continuation used by <seealso marker="#bchunk/2"> + <c>bchunk/2</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="keypos"/> + </datatype> + <datatype> + <name name="match_spec"/> + <desc> + <p>Match specifications, see the <seealso + marker="erts:match_spec">match specification</seealso> + documentation in the ERTS User's Guide and <seealso + marker="ms_transform">ms_transform(3).</seealso></p> + </desc> + </datatype> + <datatype> + <name name="no_slots"/> + </datatype> + <datatype> + <name name="object"/> + </datatype> + <datatype> + <name name="object_cont"/> + <desc> + <p>Opaque continuation used by <seealso marker="#match_object/1"> + <c>match_object/1</c></seealso> and <seealso marker="#match_object/3"> + <c>match_object/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="pattern"/> + <desc> + <p>See <seealso marker="ets#match/2">ets:match/2</seealso> for a + description of patterns.</p> + </desc> + </datatype> + <datatype> + <name name="select_cont"/> + <desc> + <p>Opaque continuation used by <seealso marker="#select/1"> + <c>select/1</c></seealso> and <seealso marker="#select/3"> + <c>select/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="tab_name"/> + </datatype> + <datatype> + <name name="type"/> + </datatype> + <datatype> + <name name="version"/> + </datatype> + </datatypes> <funcs> <func> - <name>all() -> [Name]</name> + <name name="all" arity="0"/> <fsummary>Return a list of the names of all open Dets tables on this node.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> <p>Returns a list of the names of all open tables on this node.</p> </desc> </func> <func> - <name>bchunk(Name, Continuation) -> {Continuation2, Data} | '$end_of_table' | {error, Reason}</name> + <name name="bchunk" arity="2"/> <fsummary>Return a chunk of objects stored in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Continuation = start | cont()</v> - <v>Continuation2 = cont()</v> - <v>Data = binary() | tuple()</v> - </type> <desc> <p>Returns a list of objects stored in a table. The exact representation of the returned objects is not public. The lists of data can be used for initializing a table by giving the value <c>bchunk</c> to the <c>format</c> option of the - <c>init_table/3</c> function. The Mnesia application uses this + <seealso marker="#init_table/3"><c>init_table/3</c></seealso> + function. The Mnesia application uses this function for copying open tables.</p> <p>Unless the table is protected using <c>safe_fixtable/2</c>, calls to <c>bchunk/2</c> may not work as expected if @@ -151,24 +200,23 @@ version() = 8 | 9 | default </pre> <p>The first time <c>bchunk/2</c> is called, an initial continuation, the atom <c>start</c>, must be provided.</p> <p>The <c>bchunk/2</c> function returns a tuple - <c>{Continuation2, Data}</c>, where <c>Data</c> is a list of - objects. <c>Continuation2</c> is another continuation which is + <c>{<anno>Continuation2</anno>, <anno>Data</anno>}</c>, + where <c><anno>Data</anno></c> is a list of + objects. <c><anno>Continuation2</anno></c> is another continuation + which is to be passed on to a subsequent call to <c>bchunk/2</c>. With a series of calls to <c>bchunk/2</c> it is possible to extract all objects of the table. </p> <p><c>bchunk/2</c> returns <c>'$end_of_table'</c> when all - objects have been returned, or <c>{error, Reason}</c> if an - error occurs. + objects have been returned, or <c>{error, <anno>Reason</anno>}</c> + if an error occurs. </p> </desc> </func> <func> - <name>close(Name) -> ok | {error, Reason} </name> + <name name="close" arity="1"/> <fsummary>Close a Dets table.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> <p>Closes a table. Only processes that have opened a table are allowed to close it. @@ -180,22 +228,16 @@ version() = 8 | 9 | default </pre> </desc> </func> <func> - <name>delete(Name, Key) -> ok | {error, Reason}</name> + <name name="delete" arity="2"/> <fsummary>Delete all objects with a given key from a Dets table.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> - <p>Deletes all objects with the key <c>Key</c> from the table - <c>Name</c>.</p> + <p>Deletes all objects with the key <c><anno>Key</anno></c> from + the table <c><anno>Name</anno></c>.</p> </desc> </func> <func> - <name>delete_all_objects(Name) -> ok | {error, Reason}</name> + <name name="delete_all_objects" arity="1"/> <fsummary>Delete all objects from a Dets table.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> <p>Deletes all objects from a table in almost constant time. However, if the table if fixed, <c>delete_all_objects(T)</c> @@ -203,12 +245,8 @@ version() = 8 | 9 | default </pre> </desc> </func> <func> - <name>delete_object(Name, Object) -> ok | {error, Reason}</name> + <name name="delete_object" arity="2"/> <fsummary>Delete a given object from a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Object = object()</v> - </type> <desc> <p>Deletes all instances of a given object from a table. If a table is of type <c>bag</c> or <c>duplicate_bag</c>, the @@ -218,18 +256,15 @@ version() = 8 | 9 | default </pre> </desc> </func> <func> - <name>first(Name) -> Key | '$end_of_table'</name> + <name name="first" arity="1"/> <fsummary>Return the first key stored in a Dets table.</fsummary> - <type> - <v>Key = term()</v> - <v>Name = name()</v> - </type> <desc> - <p>Returns the first key stored in the table <c>Name</c> + <p>Returns the first key stored in the table <c><anno>Name</anno></c> according to the table's internal order, or <c>'$end_of_table'</c> if the table is empty.</p> <p>Unless the table is protected using <c>safe_fixtable/2</c>, - subsequent calls to <c>next/2</c> may not work as expected if + subsequent calls to <seealso marker="#next/2"><c>next/2</c></seealso> + may not work as expected if concurrent updates are made to the table.</p> <p>Should an error occur, the process is exited with an error tuple <c>{error, Reason}</c>. The reason for not returning the @@ -243,107 +278,78 @@ version() = 8 | 9 | default </pre> </desc> </func> <func> - <name>foldl(Function, Acc0, Name) -> Acc1 | {error, Reason}</name> - <fsummary>Fold a function over a Dets table.</fsummary> - <type> - <v>Function = fun(Object, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Name = name()</v> - <v>Object = object()</v> - </type> - <desc> - <p>Calls <c>Function</c> on successive elements of the table - <c>Name</c> together with an extra argument <c>AccIn</c>. The - order in which the elements of the table are traversed is - unspecified. <c>Function</c> must return a new accumulator - which is passed to the next call. <c>Acc0</c> is returned if - the table is empty.</p> - </desc> - </func> - <func> - <name>foldr(Function, Acc0, Name) -> Acc1 | {error, Reason}</name> + <name name="foldl" arity="3"/> + <name name="foldr" arity="3"/> <fsummary>Fold a function over a Dets table.</fsummary> - <type> - <v>Function = fun(Object, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Name = name()</v> - <v>Object = object()</v> - </type> <desc> - <p>Calls <c>Function</c> on successive elements of the table - <c>Name</c> together with an extra argument <c>AccIn</c>. The + <p>Calls <c><anno>Function</anno></c> on successive elements of + the table <c><anno>Name</anno></c> together with an extra argument + <c>AccIn</c>. The order in which the elements of the table are traversed is - unspecified. <c>Function</c> must return a new accumulator - which is passed to the next call. <c>Acc0</c> is returned if + unspecified. <c><anno>Function</anno></c> must return a new + accumulator which is passed to the next call. + <c><anno>Acc0</anno></c> is returned if the table is empty.</p> </desc> </func> <func> - <name>from_ets(Name, EtsTab) -> ok | {error, Reason}</name> + <name name="from_ets" arity="2"/> <fsummary>Replace the objects of a Dets table with the objects of an Ets table.</fsummary> - <type> - <v>Name = name()</v> - <v>EtsTab = - see ets(3) -</v> - </type> <desc> - <p>Deletes all objects of the table <c>Name</c> and then - inserts all the objects of the Ets table <c>EtsTab</c>. The - order in which the objects are inserted is not specified. + <p>Deletes all objects of the table <c><anno>Name</anno></c> and then + inserts all the objects of the Ets table <c><anno>EtsTab</anno></c>. + The order in which the objects are inserted is not specified. Since <c>ets:safe_fixtable/2</c> is called the Ets table must be public or owned by the calling process.</p> </desc> </func> <func> - <name>info(Name) -> InfoList | undefined</name> + <name name="info" arity="1"/> <fsummary>Return information about a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>InfoList = [{Item, Value}]</v> - </type> <desc> - <p>Returns information about the table <c>Name</c> as a list of - <c>{Item, Value}</c> tuples:</p> + <p>Returns information about the table <c><anno>Name</anno></c> + as a list of tuples:</p> <list type="bulleted"> <item> - <p><c>{file_size, int()}</c>, the size of the file in + <p><c>{file_size, integer() >= 0}</c>, the size of the file in bytes.</p> </item> <item> - <p><c>{filename, file()}</c>, the name of the file - where objects are stored.</p> + <p><c>{filename, <seealso marker="file#type-name">file:name()</seealso>}</c>, + the name of the file where objects are stored.</p> </item> <item> - <p><c>{keypos, keypos()}</c>, the position of the - key.</p> + <p><c>{keypos, <seealso marker="#type-keypos">keypos()</seealso>} + </c>, the position of the key.</p> </item> <item> - <p><c>{size, int()}</c>, the number of objects stored + <p><c>{size, integer() >= 0}</c>, the number of objects stored in the table.</p> </item> <item> - <p><c>{type, type()}</c>, the type of the table.</p> + <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>, + the type of the table.</p> </item> </list> </desc> </func> <func> - <name>info(Name, Item) -> Value | undefined</name> + <name name="info" arity="2"/> <fsummary>Return the information associated with a given item for a Dets table.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> - <p>Returns the information associated with <c>Item</c> for the - table <c>Name</c>. In addition to the <c>{Item, Value}</c> + <p>Returns the information associated with <c><anno>Item</anno></c> + for the table <c><anno>Name</anno></c>. + In addition to the <c>{<anno>Item</anno>, <anno>Value</anno>}</c> pairs defined for <c>info/1</c>, the following items are allowed:</p> <list type="bulleted"> <item> - <p><c>{access, access()}</c>, the access mode.</p> + <p><c>{access, <seealso marker="#type-access">access()</seealso>} + </c>, the access mode.</p> </item> <item> - <p><c>{auto_save, auto_save()}</c>, the auto save - interval.</p> + <p><c>{auto_save, <seealso marker="#type-auto_save"> + auto_save()</seealso>}</c>, the auto save interval.</p> </item> <item> <p><c>{bchunk_format, binary()}</c>, an opaque binary @@ -362,21 +368,22 @@ version() = 8 | 9 | default </pre> <c>erlang:phash2/1</c> BIF is used.</p> </item> <item> - <p><c>{memory, int()}</c>, the size of the file in + <p><c>{memory, integer() >= 0}</c>, the size of the file in bytes. The same value is associated with the item <c>file_size</c>.</p> </item> <item> - <p><c>{no_keys, int()}</c>, the number of different + <p><c>{no_keys, integer >= 0()}</c>, the number of different keys stored in the table. Only available for version 9 tables.</p> </item> <item> - <p><c>{no_objects, int()}</c>, the number of objects + <p><c>{no_objects, integer >= 0()}</c>, the number of objects stored in the table.</p> </item> <item> - <p><c>{no_slots, {Min, Used, Max}}</c>, the number of + <p><c>{no_slots, {</c>Min<c>, </c>Used<c>, </c>Max<c>}}</c>, + the number of slots of the table. <c>Min</c> is the minimum number of slots, <c>Used</c> is the number of currently used slots, and <c>Max</c> is the maximum number of slots. Only @@ -387,7 +394,7 @@ version() = 8 | 9 | default </pre> handles requests to the Dets table.</p> </item> <item> - <p><c>{ram_file, bool()}</c>, whether the table is + <p><c>{ram_file, boolean()}</c>, whether the table is kept in RAM.</p> </item> <item> @@ -399,32 +406,28 @@ version() = 8 | 9 | default </pre> table is not fixed, SafeFixed is the atom <c>false</c>.</p> </item> <item> - <p><c>{version, int()}</c>, the version of the format - of the table.</p> + <p><c>{version, integer()</c>, the version of the format of + the table.</p> </item> </list> </desc> </func> <func> - <name>init_table(Name, InitFun [, Options]) -> ok | {error, Reason}</name> + <name name="init_table" arity="2"/> + <name name="init_table" arity="3"/> <fsummary>Replace all objects of a Dets table.</fsummary> - <type> - <v>Name = atom()</v> - <v>InitFun = fun(Arg) -> Res</v> - <v>Arg = read | close</v> - <v>Res = end_of_input | {[object()], InitFun} | {Data, InitFun} | term()</v> - <v>Data = binary() | tuple()</v> - </type> <desc> - <p>Replaces the existing objects of the table <c>Name</c> with - objects created by calling the input function <c>InitFun</c>, + <p>Replaces the existing objects of the table <c><anno>Name</anno></c> + with objects created by calling the input function + <c><anno>InitFun</anno></c>, see below. The reason for using this function rather than calling <c>insert/2</c> is that of efficiency. It should be noted that the input functions are called by the process that handles requests to the Dets table, not by the calling process.</p> <p>When called with the argument <c>read</c> the function - <c>InitFun</c> is assumed to return <c>end_of_input</c> when + <c><anno>InitFun</anno></c> is assumed to return + <c>end_of_input</c> when there is no more input, or <c>{Objects, Fun}</c>, where <c>Objects</c> is a list of objects and <c>Fun</c> is a new input function. Any other value Value is returned as an error @@ -448,7 +451,8 @@ version() = 8 | 9 | default </pre> item <c>no_slots</c>. See also the <c>min_no_slots</c> option below. </p> - <p>The <c>Options</c> argument is a list of <c>{Key, Val}</c> + <p>The <c><anno>Options</anno></c> argument is a list of + <c>{Key, Val}</c> tuples where the following values are allowed:</p> <list type="bulleted"> <item> @@ -461,87 +465,68 @@ version() = 8 | 9 | default </pre> </item> <item> <p><c>{format, Format}</c>. Specifies the format of the - objects returned by the function <c>InitFun</c>. If + objects returned by the function <c><anno>InitFun</anno></c>. If <c>Format</c> is <c>term</c> (the default), - <c>InitFun</c> is assumed to return a list of tuples. If - <c>Format</c> is <c>bchunk</c>, <c>InitFun</c> is - assumed to return <c>Data</c> as returned by - <c>bchunk/2</c>. This option overrides the + <c><anno>InitFun</anno></c> is assumed to return a list of tuples. If + <c>Format</c> is <c>bchunk</c>, <c><anno>InitFun</anno></c> is + assumed to return <c><anno>Data</anno></c> as returned by + <seealso marker="#bchunk/2"><c>bchunk/2</c></seealso>. + This option overrides the <c>min_no_slots</c> option.</p> </item> </list> </desc> </func> <func> - <name>insert(Name, Objects) -> ok | {error, Reason}</name> + <name name="insert" arity="2"/> <fsummary>Insert one or more objects into a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Objects = object() | [object()]</v> - </type> <desc> - <p>Inserts one or more objects into the table <c>Name</c>. If - there already exists an object with a key matching the key of + <p>Inserts one or more objects into the table <c><anno>Name</anno></c>. + If there already exists an object with a key matching the key of some of the given objects and the table type is <c>set</c>, the old object will be replaced.</p> </desc> </func> <func> - <name>insert_new(Name, Objects) -> Bool</name> + <name name="insert_new" arity="2"/> <fsummary>Insert one or more objects into a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Objects = object() | [object()]</v> - <v>Bool = bool()</v> - </type> <desc> - <p>Inserts one or more objects into the table <c>Name</c>. If - there already exists some object with a key matching the key + <p>Inserts one or more objects into the table <c><anno>Name</anno></c>. + If there already exists some object with a key matching the key of any of the given objects the table is not updated and <c>false</c> is returned, otherwise the objects are inserted and <c>true</c> returned.</p> </desc> </func> <func> - <name>is_compatible_bchunk_format(Name, BchunkFormat) -> Bool</name> + <name name="is_compatible_bchunk_format" arity="2"/> <fsummary>Test compatibility of a table's chunk data.</fsummary> - <type> - <v>Name = name()</v> - <v>BchunkFormat = binary()</v> - <v>Bool = bool()</v> - </type> <desc> <p>Returns <c>true</c> if it would be possible to initialize - the table <c>Name</c>, using <c>init_table/3</c> with the + the table <c><anno>Name</anno></c>, using + <seealso marker="#init_table/3"><c>init_table/3</c></seealso> + with the option <c>{format, bchunk}</c>, with objects read with - <c>bchunk/2</c> from some table <c>T</c> such that calling + <seealso marker="#bchunk/2"><c>bchunk/2</c></seealso> from some + table <c>T</c> such that calling <c>info(T, bchunk_format)</c> returns <c>BchunkFormat</c>.</p> </desc> </func> <func> - <name>is_dets_file(FileName) -> Bool | {error, Reason}</name> + <name name="is_dets_file" arity="1"/> <fsummary>Test for a Dets table.</fsummary> - <type> - <v>FileName = file()</v> - <v>Bool = bool()</v> - </type> <desc> - <p>Returns <c>true</c> if the file <c>FileName</c> is a Dets - table, <c>false</c> otherwise.</p> + <p>Returns <c>true</c> if the file <c><anno>Filename</anno></c> + is a Dets table, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>lookup(Name, Key) -> [Object] | {error, Reason}</name> + <name name="lookup" arity="2"/> <fsummary>Return all objects with a given key stored in a Dets table.</fsummary> - <type> - <v>Key = term()</v> - <v>Name = name()</v> - <v>Object = object()</v> - </type> <desc> - <p>Returns a list of all objects with the key <c>Key</c> - stored in the table <c>Name</c>. For example:</p> + <p>Returns a list of all objects with the key <c><anno>Key</anno></c> + stored in the table <c><anno>Name</anno></c>. For example:</p> <pre> 2> <input>dets:open_file(abc, [{type, bag}]).</input> {ok,abc} @@ -562,71 +547,57 @@ ok </desc> </func> <func> - <name>match(Continuation) -> {[Match], Continuation2} | '$end_of_table' | {error, Reason}</name> + <name name="match" arity="1"/> <fsummary>Match a chunk of objects stored in a Dets table and return a list of variable bindings.</fsummary> - <type> - <v>Continuation = Continuation2 = bindings_cont()</v> - <v>Match = [term()]</v> - </type> <desc> <p>Matches some objects stored in a table and returns a non-empty list of the bindings that match a given pattern in some unspecified order. The table, the pattern, and the number of objects that are matched are all defined by - <c>Continuation</c>, which has been returned by a prior call - to <c>match/1</c> or <c>match/3</c>.</p> + <c><anno>Continuation</anno></c>, which has been returned by a prior + call to <c>match/1</c> or <c>match/3</c>.</p> <p>When all objects of the table have been matched, <c>'$end_of_table'</c> is returned.</p> </desc> </func> <func> - <name>match(Name, Pattern) -> [Match] | {error, Reason}</name> + <name name="match" arity="2"/> <fsummary>Match the objects stored in a Dets table and return a list of variable bindings.</fsummary> - <type> - <v>Name = name()</v> - <v>Pattern = tuple()</v> - <v>Match = [term()]</v> - </type> <desc> - <p>Returns for each object of the table <c>Name</c> that - matches <c>Pattern</c> a list of bindings in some unspecified - order. See <seealso marker="ets">ets(3)</seealso> for a + <p>Returns for each object of the table <c><anno>Name</anno></c> that + matches <c><anno>Pattern</anno></c> a list of bindings in some unspecified + order. See <seealso marker="ets#match/2">ets:match/2</seealso> for a description of patterns. If the keypos'th element of - <c>Pattern</c> is unbound, all objects of the table are + <c><anno>Pattern</anno></c> is unbound, all objects of the table are matched. If the keypos'th element is bound, only the objects with the right key are matched.</p> </desc> </func> <func> - <name>match(Name, Pattern, N) -> {[Match], Continuation} | '$end_of_table' | {error, Reason}</name> + <name name="match" arity="3"/> <fsummary>Match the first chunk of objects stored in a Dets table and return a list of variable bindings.</fsummary> - <type> - <v>Name = name()</v> - <v>Pattern = tuple()</v> - <v>N = default | int()</v> - <v>Match = [term()]</v> - <v>Continuation = bindings_cont()</v> - </type> <desc> - <p>Matches some or all objects of the table <c>Name</c> and + <p>Matches some or all objects of the table <c><anno>Name</anno></c> and returns a non-empty list of the bindings that match - <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of - patterns.</p> + <c><anno>Pattern</anno></c> in some unspecified order. + See <seealso marker="ets#match/2">ets:match/2</seealso> for a + description of patterns.</p> <p>A tuple of the bindings and a continuation is returned, unless the table is empty, in which case <c>'$end_of_table'</c> is returned. The continuation is to be used when matching further objects by calling - <c>match/1</c>.</p> - <p>If the keypos'th element of <c>Pattern</c> is bound, all - objects of the table are matched. If the keypos'th element is - unbound, all objects of the table are matched, <c>N</c> + <seealso marker="#match/1"><c>match/1</c></seealso>.</p> + <p>If the keypos'th element of <c><anno>Pattern</anno></c> is bound, + all objects of the table are matched. If the keypos'th element is + unbound, all objects of the table are matched, <c><anno>N</anno></c> objects at a time, until at least one object matches or the end of the table has been reached. The default, indicated by - giving <c>N</c> the value <c>default</c>, is to let the number + giving <c><anno>N</anno></c> the value <c>default</c>, + is to let the number of objects vary depending on the sizes of the objects. If - <c>Name</c> is a version 9 table, all objects with the same + <c><anno>Name</anno></c> is a version 9 table, all objects with the same key are always matched at the same time which implies that - more than N objects may sometimes be matched. + more than <anno>N</anno> objects may sometimes be matched. </p> <p>The table should always be protected using <c>safe_fixtable/2</c> before calling <c>match/3</c>, or @@ -634,15 +605,11 @@ ok </desc> </func> <func> - <name>match_delete(Name, Pattern) -> ok | {error, Reason}</name> + <name name="match_delete" arity="2"/> <fsummary>Delete all objects that match a given pattern from a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Pattern = tuple()</v> - </type> <desc> - <p>Deletes all objects that match <c>Pattern</c> from the - table <c>Name</c>. + <p>Deletes all objects that match <c><anno>Pattern</anno></c> from the + table <c><anno>Name</anno></c>. See <seealso marker="ets#match/2">ets:match/2</seealso> for a description of patterns.</p> <p>If the keypos'th element of <c>Pattern</c> is bound, @@ -650,17 +617,13 @@ ok </desc> </func> <func> - <name>match_object(Continuation) -> {[Object], Continuation2} | '$end_of_table' | {error, Reason}</name> + <name name="match_object" arity="1"/> <fsummary>Match a chunk of objects stored in a Dets table and return a list of objects.</fsummary> - <type> - <v>Continuation = Continuation2 = object_cont()</v> - <v>Object = object()</v> - </type> <desc> <p>Returns a non-empty list of some objects stored in a table that match a given pattern in some unspecified order. The table, the pattern, and the number of objects that are matched - are all defined by <c>Continuation</c>, which has been + are all defined by <c><anno>Continuation</anno></c>, which has been returned by a prior call to <c>match_object/1</c> or <c>match_object/3</c>.</p> <p>When all objects of the table have been matched, @@ -668,20 +631,17 @@ ok </desc> </func> <func> - <name>match_object(Name, Pattern) -> [Object] | {error, Reason}</name> + <name name="match_object" arity="2"/> <fsummary>Match the objects stored in a Dets table and return a list of objects.</fsummary> - <type> - <v>Name = name()</v> - <v>Pattern = tuple()</v> - <v>Object = object()</v> - </type> <desc> - <p>Returns a list of all objects of the table <c>Name</c> that - match <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of patterns. + <p>Returns a list of all objects of the table <c><anno>Name</anno></c> that + match <c><anno>Pattern</anno></c> in some unspecified order. + See <seealso marker="ets#match/2">ets:match/2</seealso> for a + description of patterns. </p> - <p>If the keypos'th element of <c>Pattern</c> is + <p>If the keypos'th element of <c><anno>Pattern</anno></c> is unbound, all objects of the table are matched. If the - keypos'th element of <c>Pattern</c> is bound, only the + keypos'th element of <c><anno>Pattern</anno></c> is bound, only the objects with the right key are matched.</p> <p>Using the <c>match_object</c> functions for traversing all objects of a table is more efficient than calling @@ -689,34 +649,28 @@ ok </desc> </func> <func> - <name>match_object(Name, Pattern, N) -> {[Object], Continuation} | '$end_of_table' | {error, Reason}</name> + <name name="match_object" arity="3"/> <fsummary>Match the first chunk of objects stored in a Dets table and return a list of objects.</fsummary> - <type> - <v>Name = name()</v> - <v>Pattern = tuple()</v> - <v>N = default | int()</v> - <v>Object = object()</v> - <v>Continuation = object_cont()</v> - </type> <desc> - <p>Matches some or all objects stored in the table <c>Name</c> + <p>Matches some or all objects stored in the table <c><anno>Name</anno></c> and returns a non-empty list of the objects that match - <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of - patterns.</p> + <c><anno>Pattern</anno></c> in some unspecified order. + See <seealso marker="ets#match/2">ets:match/2</seealso> for a + description of patterns.</p> <p>A list of objects and a continuation is returned, unless the table is empty, in which case <c>'$end_of_table'</c> is returned. The continuation is to be used when matching further objects by calling <c>match_object/1</c>.</p> - <p>If the keypos'th element of <c>Pattern</c> is bound, all + <p>If the keypos'th element of <c><anno>Pattern</anno></c> is bound, all objects of the table are matched. If the keypos'th element is - unbound, all objects of the table are matched, <c>N</c> + unbound, all objects of the table are matched, <c><anno>N</anno></c> objects at a time, until at least one object matches or the end of the table has been reached. The default, indicated by - giving <c>N</c> the value <c>default</c>, is to let the number + giving <c><anno>N</anno></c> the value <c>default</c>, is to let the number of objects vary depending on the sizes of the objects. If - <c>Name</c> is a version 9 table, all matching objects with + <c><anno>Name</anno></c> is a version 9 table, all matching objects with the same key are always returned in the same reply which - implies that more than N objects may sometimes be returned. + implies that more than <anno>N</anno> objects may sometimes be returned. </p> <p>The table should always be protected using <c>safe_fixtable/2</c> before calling <c>match_object/3</c>, @@ -724,43 +678,31 @@ ok </desc> </func> <func> - <name>member(Name, Key) -> Bool | {error, Reason}</name> + <name name="member" arity="2"/> <fsummary>Test for occurrence of a key in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Key = term()</v> - <v>Bool = bool()</v> - </type> <desc> <p>Works like <c>lookup/2</c>, but does not return the objects. The function returns <c>true</c> if one or more - elements of the table has the key <c>Key</c>, <c>false</c> + elements of the table has the key <c><anno>Key</anno></c>, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>next(Name, Key1) -> Key2 | '$end_of_table'</name> + <name name="next" arity="2"/> <fsummary>Return the next key in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Key1 = Key2 = term()</v> - </type> <desc> - <p>Returns the key following <c>Key1</c> in the table - <c>Name</c> according to the table's internal order, or + <p>Returns the key following <c><anno>Key1</anno></c> in the table + <c><anno>Name</anno></c> according to the table's internal order, or <c>'$end_of_table'</c> if there is no next key.</p> <p>Should an error occur, the process is exited with an error tuple <c>{error, Reason}</c>.</p> - <p>Use <c>first/1</c> to find the first key in the table.</p> + <p>Use <seealso marker="#first/1"><c>first/1</c></seealso> to find + the first key in the table.</p> </desc> </func> <func> - <name>open_file(Filename) -> {ok, Reference} | {error, Reason}</name> + <name name="open_file" arity="1"/> <fsummary>Open an existing Dets table.</fsummary> - <type> - <v>FileName = file()</v> - <v>Reference = reference()</v> - </type> <desc> <p>Opens an existing table. If the table has not been properly closed, it will be repaired. The returned reference is to be @@ -769,15 +711,12 @@ ok </desc> </func> <func> - <name>open_file(Name, Args) -> {ok, Name} | {error, Reason}</name> + <name name="open_file" arity="2"/> <fsummary>Open a Dets table.</fsummary> - <type> - <v>Name = atom()</v> - </type> <desc> <p>Opens a table. An empty Dets table is created if no file exists.</p> - <p>The atom <c>Name</c> is the name of the table. The table + <p>The atom <c><anno>Name</anno></c> is the name of the table. The table name must be provided in all subsequent operations on the table. The name can be used by other processes as well, and several process can share one table. @@ -786,18 +725,20 @@ ok name and arguments, then the table will have two users. If one user closes the table, it still remains open until the second user closes the table.</p> - <p>The <c>Args</c> argument is a list of <c>{Key, Val}</c> + <p>The <c><anno>Args</anno></c> argument is a list of <c>{Key, Val}</c> tuples where the following values are allowed:</p> <list type="bulleted"> <item> - <p><c>{access, access()}</c>. It is possible to open + <p><c>{access, <seealso marker="#type-access"> + access()</seealso>}</c>. It is possible to open existing tables in read-only mode. A table which is opened in read-only mode is not subjected to the automatic file reparation algorithm if it is later opened after a crash. The default value is <c>read_write</c>.</p> </item> <item> - <p><c>{auto_save, auto_save()}</c>, the auto save + <p><c>{auto_save, <seealso marker="#type-auto_save"> + auto_save()</seealso>}</c>, the auto save interval. If the interval is an integer <c>Time</c>, the table is flushed to disk whenever it is not accessed for <c>Time</c> milliseconds. A table that has been flushed @@ -807,15 +748,18 @@ ok is 180000 (3 minutes).</p> </item> <item> - <p><c>{estimated_no_objects, int()}</c>. Equivalent to the + <p><c>{estimated_no_objects, <seealso marker="#type-no_slots"> + no_slots()</seealso>}</c>. Equivalent to the <c>min_no_slots</c> option.</p> </item> <item> - <p><c>{file, file()}</c>, the name of the file to be + <p><c>{file, <seealso marker="file#type-name"> + file:name()</seealso>}</c>, the name of the file to be opened. The default value is the name of the table.</p> </item> <item> - <p><c>{max_no_slots, no_slots()}</c>, the maximum number + <p><c>{max_no_slots, <seealso marker="#type-no_slots"> + no_slots()</seealso>}</c>, the maximum number of slots that will be used. The default value as well as the maximal value is 32 M. Note that a higher value may increase the fragmentation of the table, and conversely, @@ -824,14 +768,16 @@ ok 9 tables.</p> </item> <item> - <p><c>{min_no_slots, no_slots()}</c>. Application + <p><c>{min_no_slots, <seealso marker="#type-no_slots"> + no_slots()</seealso>}</c>. Application performance can be enhanced with this flag by specifying, when the table is created, the estimated number of different keys that will be stored in the table. The default value as well as the minimum value is 256.</p> </item> <item> - <p><c>{keypos, keypos()}</c>, the position of the + <p><c>{keypos, <seealso marker="#type-keypos"> + keypos()</seealso>}</c>, the position of the element of each object to be used as key. The default value is 1. The ability to explicitly state the key position is most convenient when we want to store Erlang @@ -839,7 +785,7 @@ ok name of the record type.</p> </item> <item> - <p><c>{ram_file, bool()}</c>, whether the table is to + <p><c>{ram_file, boolean()}</c>, whether the table is to be kept in RAM. Keeping the table in RAM may sound like an anomaly, but can enhance the performance of applications which open a table, insert a set of objects, and then @@ -849,7 +795,7 @@ ok </item> <item> <p><c>{repair, Value}</c>. <c>Value</c> can be either - a <c>bool()</c> or the atom <c>force</c>. The flag + a <c>boolean()</c> or the atom <c>force</c>. The flag specifies whether the Dets server should invoke the automatic file reparation algorithm. The default is <c>true</c>. If <c>false</c> is specified, there is no @@ -868,11 +814,12 @@ ok already open.</p> </item> <item> - <p><c>{type, type()}</c>, the type of the table. The - default value is <c>set</c>.</p> + <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>, + the type of the table. The default value is <c>set</c>.</p> </item> <item> - <p><c>{version, version()}</c>, the version of the format + <p><c>{version, <seealso marker="#type-version"> + version()</seealso>}</c>, the version of the format used for the table. The default value is <c>9</c>. Tables on the format used before OTP R8 can be created by giving the value <c>8</c>. A version 8 table can be converted to @@ -883,12 +830,8 @@ ok </desc> </func> <func> - <name>pid2name(Pid) -> {ok, Name} | undefined</name> + <name name="pid2name" arity="1"/> <fsummary>Return the name of the Dets table handled by a pid.</fsummary> - <type> - <v>Name = name()</v> - <v>Pid = pid()</v> - </type> <desc> <p>Returns the name of the table given the pid of a process that handles requests to a table, or <c>undefined</c> if @@ -897,12 +840,8 @@ ok </desc> </func> <func> - <name>repair_continuation(Continuation, MatchSpec) -> Continuation2</name> + <name name="repair_continuation" arity="2"/> <fsummary>Repair a continuation from select/1 or select/3.</fsummary> - <type> - <v>Continuation = Continuation2 = select_cont()</v> - <v>MatchSpec = match_spec()</v> - </type> <desc> <p>This function can be used to restore an opaque continuation returned by <c>select/3</c> or <c>select/1</c> if the @@ -932,14 +871,11 @@ ok </desc> </func> <func> - <name>safe_fixtable(Name, Fix)</name> + <name name="safe_fixtable" arity="2"/> <fsummary>Fix a Dets table for safe traversal.</fsummary> - <type> - <v>Name = name()</v> - <v>Fix = bool()</v> - </type> <desc> - <p>If <c>Fix</c> is <c>true</c>, the table <c>Name</c> is + <p>If <c><anno>Fix</anno></c> is <c>true</c>, the table + <c><anno>Name</anno></c> is fixed (once more) by the calling process, otherwise the table is released. The table is also released when a fixing process terminates. @@ -961,17 +897,13 @@ ok </desc> </func> <func> - <name>select(Continuation) -> {Selection, Continuation2} | '$end_of_table' | {error, Reason}</name> + <name name="select" arity="1"/> <fsummary>Apply a match specification to some objects stored in a Dets table.</fsummary> - <type> - <v>Continuation = Continuation2 = select_cont()</v> - <v>Selection = [term()]</v> - </type> <desc> <p>Applies a match specification to some objects stored in a table and returns a non-empty list of the results. The table, the match specification, and the number of objects - that are matched are all defined by <c>Continuation</c>, + that are matched are all defined by <c><anno>Continuation</anno></c>, which has been returned by a prior call to <c>select/1</c> or <c>select/3</c>.</p> <p>When all objects of the table have been matched, @@ -979,20 +911,15 @@ ok </desc> </func> <func> - <name>select(Name, MatchSpec) -> Selection | {error, Reason}</name> + <name name="select" arity="2"/> <fsummary>Apply a match specification to all objects stored in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>MatchSpec = match_spec()</v> - <v>Selection = [term()]</v> - </type> <desc> <p>Returns the results of applying the match specification - <c>MatchSpec</c> to all or some objects stored in the table - <c>Name</c>. The order of the objects is not specified. See + <c><anno>MatchSpec</anno></c> to all or some objects stored in the table + <c><anno>Name</anno></c>. The order of the objects is not specified. See the ERTS User's Guide for a description of match specifications.</p> - <p>If the keypos'th element of <c>MatchSpec</c> is + <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is unbound, the match specification is applied to all objects of the table. If the keypos'th element is bound, the match specification is applied to the objects with the right key(s) @@ -1004,19 +931,12 @@ ok </desc> </func> <func> - <name>select(Name, MatchSpec, N) -> {Selection, Continuation} | '$end_of_table' | {error, Reason}</name> + <name name="select" arity="3"/> <fsummary>Apply a match specification to the first chunk of objects stored in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>MatchSpec = match_spec()</v> - <v>N = default | int()</v> - <v>Selection = [term()]</v> - <v>Continuation = select_cont()</v> - </type> <desc> <p>Returns the results of applying the match specification - <c>MatchSpec</c> to some or all objects stored in the table - <c>Name</c>. The order of the objects is not specified. See + <c><anno>MatchSpec</anno></c> to some or all objects stored in the table + <c><anno>Name</anno></c>. The order of the objects is not specified. See the ERTS User's Guide for a description of match specifications.</p> <p>A tuple of the results of applying the match specification @@ -1024,18 +944,18 @@ ok in which case <c>'$end_of_table'</c> is returned. The continuation is to be used when matching further objects by calling <c>select/1</c>.</p> - <p>If the keypos'th element of <c>MatchSpec</c> is bound, the + <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is bound, the match specification is applied to all objects of the table with the right key(s). If the keypos'th element of - <c>MatchSpec</c> is unbound, the match specification is - applied to all objects of the table, <c>N</c> objects at a + <c><anno>MatchSpec</anno></c> is unbound, the match specification is + applied to all objects of the table, <c><anno>N</anno></c> objects at a time, until at least one object matches or the end of the table has been reached. The default, indicated by giving - <c>N</c> the value <c>default</c>, is to let the number of + <c><anno>N</anno></c> the value <c>default</c>, is to let the number of objects vary depending on the sizes of the objects. If - <c>Name</c> is a version 9 table, all objects with the same + <c><anno>Name</anno></c> is a version 9 table, all objects with the same key are always handled at the same time which implies that the - match specification may be applied to more than N objects. + match specification may be applied to more than <anno>N</anno> objects. </p> <p>The table should always be protected using <c>safe_fixtable/2</c> before calling <c>select/3</c>, or @@ -1043,48 +963,35 @@ ok </desc> </func> <func> - <name>select_delete(Name, MatchSpec) -> N | {error, Reason}</name> + <name name="select_delete" arity="2"/> <fsummary>Delete all objects that match a given pattern from a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>MatchSpec = match_spec()</v> - <v>N = int()</v> - </type> <desc> - <p>Deletes each object from the table <c>Name</c> such that - applying the match specification <c>MatchSpec</c> to the + <p>Deletes each object from the table <c><anno>Name</anno></c> such that + applying the match specification <c><anno>MatchSpec</anno></c> to the object returns the value <c>true</c>. See the ERTS User's Guide for a description of match specifications. Returns the number of deleted objects.</p> - <p>If the keypos'th element of <c>MatchSpec</c> is + <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is bound, the match specification is applied to the objects with the right key(s) only.</p> </desc> </func> <func> - <name>slot(Name, I) -> '$end_of_table' | [Object] | {error, Reason}</name> + <name name="slot" arity="2"/> <fsummary>Return the list of objects associated with a slot of a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>I = int()</v> - <v>Object = object()</v> - </type> <desc> <p>The objects of a table are distributed among slots, starting with slot <c>0</c> and ending with slot n. This function returns the list of objects associated with slot - <c>I</c>. If <c>I</c> is greater than n <c>'$end_of_table'</c> - is returned.</p> + <c><anno>I</anno></c>. If <c><anno>I</anno></c> is greater than n + <c>'$end_of_table'</c> is returned.</p> </desc> </func> <func> - <name>sync(Name) -> ok | {error, Reason}</name> + <name name="sync" arity="1"/> <fsummary>Ensure that all updates made to a Dets table are written to disk.</fsummary> - <type> - <v>Name = name()</v> - </type> <desc> - <p>Ensures that all updates made to the table <c>Name</c> are + <p>Ensures that all updates made to the table <c><anno>Name</anno></c> are written to disk. This also applies to tables which have been opened with the <c>ram_file</c> flag set to <c>true</c>. In this case, the contents of the RAM file are flushed to @@ -1095,25 +1002,16 @@ ok </desc> </func> <func> - <name>table(Name [, Options]) -> QueryHandle</name> + <name name="table" arity="1"/> + <name name="table" arity="2"/> <fsummary>Return a QLC query handle.</fsummary> - <type> - <v>Name = name()</v> - <v>QueryHandle = - a query handle, see qlc(3) -</v> - <v>Options = [Option] | Option</v> - <v>Option = {n_objects, Limit} | {traverse, TraverseMethod}</v> - <v>Limit = default | integer() >= 1</v> - <v>TraverseMethod = first_next | select | {select, MatchSpec}</v> - <v>MatchSpec = match_spec()</v> - </type> <desc> - <p> <marker id="qlc_table"></marker> -Returns a QLC (Query List + <p><marker id="qlc_table"></marker>Returns a QLC (Query List Comprehension) query handle. The module <c>qlc</c> implements a query language aimed mainly at Mnesia but Ets tables, Dets tables, and lists are also recognized by <c>qlc</c> as sources of data. Calling <c>dets:table/1,2</c> is the - means to make the Dets table <c>Name</c> usable to <c>qlc</c>.</p> + means to make the Dets table <c><anno>Name</anno></c> usable to <c>qlc</c>.</p> <p>When there are only simple restrictions on the key position <c>qlc</c> uses <c>dets:lookup/2</c> to look up the keys, but when that is not possible the whole table is traversed. The @@ -1137,7 +1035,8 @@ Returns a QLC (Query List specification that matches all objects.</p> </item> <item> - <p><c>{select, MatchSpec}</c>. As for <c>select</c> + <p><c>{select, <seealso marker="#type-match_spec"> + match_spec()}</seealso></c>. As for <c>select</c> the table is traversed by calling <c>dets:select/3</c> and <c>dets:select/1</c>. The difference is that the match specification is explicitly given. This is how to @@ -1166,35 +1065,23 @@ true </pre> </desc> </func> <func> - <name>to_ets(Name, EtsTab) -> EtsTab | {error, Reason}</name> + <name name="to_ets" arity="2"/> <fsummary>Insert all objects of a Dets table into an Ets table.</fsummary> - <type> - <v>Name = name()</v> - <v>EtsTab = - see ets(3) -</v> - </type> <desc> - <p>Inserts the objects of the Dets table <c>Name</c> into the - Ets table <c>EtsTab</c>. The order in which the objects are + <p>Inserts the objects of the Dets table <c><anno>Name</anno></c> into the + Ets table <c><anno>EtsTab</anno></c>. The order in which the objects are inserted is not specified. The existing objects of the Ets table are kept unless overwritten.</p> </desc> </func> <func> - <name>traverse(Name, Fun) -> Return | {error, Reason}</name> + <name name="traverse" arity="2"/> <fsummary>Apply a function to all or some objects stored in a Dets table.</fsummary> - <type> - <v>Fun = fun(Object) -> FunReturn</v> - <v>FunReturn = continue | {continue, Val} | {done, Value}</v> - <v>Val = Value = term()</v> - <v>Name = name()</v> - <v>Object = object()</v> - <v>Return = [term()]</v> - </type> <desc> - <p>Applies <c>Fun</c> to each object stored in the table - <c>Name</c> in some unspecified order. Different actions are - taken depending on the return value of <c>Fun</c>. The - following <c>Fun</c> return values are allowed:</p> + <p>Applies <c><anno>Fun</anno></c> to each object stored in the table + <c><anno>Name</anno></c> in some unspecified order. Different actions are + taken depending on the return value of <c><anno>Fun</anno></c>. The + following <c><anno>Fun</anno></c> return values are allowed:</p> <taglist> <tag><c>continue</c></tag> <item> @@ -1206,35 +1093,31 @@ fun(X) -> io:format("~p~n", [X]), continue end. </pre> </item> <tag><c>{continue, Val}</c></tag> <item> - <p>Continue the traversal and accumulate <c>Val</c>. The + <p>Continue the traversal and accumulate <c><anno>Val</anno></c>. The following function is supplied in order to collect all objects of a table in a list: </p> <pre> fun(X) -> {continue, X} end. </pre> </item> - <tag><c>{done, Value}</c></tag> + <tag><c>{done, <anno>Value</anno>}</c></tag> <item> - <p>Terminate the traversal and return <c>[Value | Acc]</c>.</p> + <p>Terminate the traversal and return <c>[<anno>Value</anno> | Acc]</c>.</p> </item> </taglist> - <p>Any other value returned by <c>Fun</c> terminates the + <p>Any other value <c><anno>OtherValue</anno></c> returned by <c><anno>Fun</anno></c> terminates the traversal and is immediately returned. </p> </desc> </func> <func> - <name>update_counter(Name, Key, Increment) -> Result</name> + <name name="update_counter" arity="3"/> <fsummary>Update a counter object stored in a Dets table.</fsummary> - <type> - <v>Name = name()</v> - <v>Key = term()</v> - <v>Increment = {Pos, Incr} | Incr</v> - <v>Pos = Incr = Result = integer()</v> - </type> <desc> - <p>Updates the object with key <c>Key</c> stored in the table - <c>Name</c> of type <c>set</c> by adding <c>Incr</c> to the - element at the <c>Pos</c>:th position. The new counter value + <p>Updates the object with key <c><anno>Key</anno></c> stored in the + table <c><anno>Name</anno></c> of type <c>set</c> by adding + <c><anno>Incr</anno></c> to the + element at the <c><anno>Pos</anno></c>:th position. + The new counter value is returned. If no position is specified, the element directly following the key is updated.</p> <p>This functions provides a way of updating a counter, @@ -1252,4 +1135,3 @@ fun(X) -> {continue, X} end. </pre> <seealso marker="qlc">qlc(3)</seealso></p> </section> </erlref> - diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml index 40e61d7d33..b01acd02bf 100644 --- a/lib/stdlib/doc/src/dict.xml +++ b/lib/stdlib/doc/src/dict.xml @@ -39,176 +39,120 @@ they do not compare equal (<c>==</c>).</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -dictionary() - as returned by new/0</code> - </section> + <datatypes> + <datatype> + <name><marker id="type-dict">dict()</marker></name> + <desc><p>Dictionary as returned by <c>new/0</c>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>append(Key, Value, Dict1) -> Dict2</name> + <name name="append" arity="3"/> <fsummary>Append a value to keys in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>This function appends a new <c>Value</c> to the current list - of values associated with <c>Key</c>. An exception is - generated if the initial value associated with <c>Key</c> is - not a list of values.</p> + <p>This function appends a new <c><anno>Value</anno></c> to the current list + of values associated with <c><anno>Key</anno></c>.</p> </desc> </func> <func> - <name>append_list(Key, ValList, Dict1) -> Dict2</name> + <name name="append_list" arity="3"/> <fsummary>Append new values to keys in a dictionary</fsummary> - <type> - <v>ValList = [Value]</v> - <v>Key = Value = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>This function appends a list of values <c>ValList</c> to - the current list of values associated with <c>Key</c>. An + <p>This function appends a list of values <c><anno>ValList</anno></c> to + the current list of values associated with <c><anno>Key</anno></c>. An exception is generated if the initial value associated with - <c>Key</c> is not a list of values.</p> + <c><anno>Key</anno></c> is not a list of values.</p> </desc> </func> <func> - <name>erase(Key, Dict1) -> Dict2</name> + <name name="erase" arity="2"/> <fsummary>Erase a key from a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> <p>This function erases all items with a given key from a dictionary.</p> </desc> </func> <func> - <name>fetch(Key, Dict) -> Value</name> + <name name="fetch" arity="2"/> <fsummary>Look-up values in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Dict = dictionary()</v> - </type> <desc> - <p>This function returns the value associated with <c>Key</c> - in the dictionary <c>Dict</c>. <c>fetch</c> assumes that - the <c>Key</c> is present in the dictionary and an exception - is generated if <c>Key</c> is not in the dictionary.</p> + <p>This function returns the value associated with <c><anno>Key</anno></c> + in the dictionary <c><anno>Dict</anno></c>. <c>fetch</c> assumes that + the <c><anno>Key</anno></c> is present in the dictionary and an exception + is generated if <c><anno>Key</anno></c> is not in the dictionary.</p> </desc> </func> <func> - <name>fetch_keys(Dict) -> Keys</name> + <name name="fetch_keys" arity="1"/> <fsummary>Return all keys in a dictionary</fsummary> - <type> - <v>Dict = dictionary()</v> - <v>Keys = [term()]</v> - </type> <desc> <p>This function returns a list of all keys in the dictionary.</p> </desc> </func> <func> - <name>filter(Pred, Dict1) -> Dict2</name> + <name name="filter" arity="2"/> <fsummary>Choose elements which satisfy a predicate</fsummary> - <type> - <v>Pred = fun(Key, Value) -> bool()</v> - <v> Key = Value = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p><c>Dict2</c> is a dictionary of all keys and values in - <c>Dict1</c> for which <c>Pred(Key, Value)</c> is <c>true</c>.</p> + <p><c><anno>Dict2</anno></c> is a dictionary of all keys and values in + <c><anno>Dict1</anno></c> for which <c><anno>Pred</anno>(<anno>Key</anno>, <anno>Value</anno>)</c> is <c>true</c>.</p> </desc> </func> <func> - <name>find(Key, Dict) -> {ok, Value} | error</name> + <name name="find" arity="2"/> <fsummary>Search for a key in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Dict = dictionary()</v> - </type> <desc> <p>This function searches for a key in a dictionary. Returns - <c>{ok, Value}</c> where <c>Value</c> is the value associated - with <c>Key</c>, or <c>error</c> if the key is not present in + <c>{ok, <anno>Value</anno>}</c> where <c><anno>Value</anno></c> is the value associated + with <c><anno>Key</anno></c>, or <c>error</c> if the key is not present in the dictionary.</p> </desc> </func> <func> - <name>fold(Fun, Acc0, Dict) -> Acc1</name> + <name name="fold" arity="3"/> <fsummary>Fold a function over a dictionary</fsummary> - <type> - <v>Fun = fun(Key, Value, AccIn) -> AccOut</v> - <v>Key = Value = term()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Dict = dictionary()</v> - </type> <desc> - <p>Calls <c>Fun</c> on successive keys and values of - <c>Dict</c> together with an extra argument <c>Acc</c> - (short for accumulator). <c>Fun</c> must return a new - accumulator which is passed to the next call. <c>Acc0</c> is + <p>Calls <c><anno>Fun</anno></c> on successive keys and values of + <c><anno>Dict</anno></c> together with an extra argument <c>Acc</c> + (short for accumulator). <c><anno>Fun</anno></c> must return a new + accumulator which is passed to the next call. <c><anno>Acc0</anno></c> is returned if the list is empty. The evaluation order is undefined.</p> </desc> </func> <func> - <name>from_list(List) -> Dict</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list of pairs to a dictionary</fsummary> - <type> - <v>List = [{Key, Value}]</v> - <v>Dict = dictionary()</v> - </type> <desc> - <p>This function converts the <c>Key</c> - <c>Value</c> list - <c>List</c> to a dictionary.</p> + <p>This function converts the <c><anno>Key</anno></c> - <c><anno>Value</anno></c> list + <c><anno>List</anno></c> to a dictionary.</p> </desc> </func> <func> - <name>is_key(Key, Dict) -> bool()</name> + <name name="is_key" arity="2"/> <fsummary>Test if a key is in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Dict = dictionary()</v> - </type> <desc> - <p>This function tests if <c>Key</c> is contained in - the dictionary <c>Dict</c>.</p> + <p>This function tests if <c><anno>Key</anno></c> is contained in + the dictionary <c><anno>Dict</anno></c>.</p> </desc> </func> <func> - <name>map(Fun, Dict1) -> Dict2</name> + <name name="map" arity="2"/> <fsummary>Map a function over a dictionary</fsummary> - <type> - <v>Fun = fun(Key, Value1) -> Value2</v> - <v> Key = Value1 = Value2 = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p><c>map</c> calls <c>Func</c> on successive keys and values - of <c>Dict</c> to return a new value for each key. + <p><c>map</c> calls <c><anno>Fun</anno></c> on successive keys and values + of <c><anno>Dict1</anno></c> to return a new value for each key. The evaluation order is undefined.</p> </desc> </func> <func> - <name>merge(Fun, Dict1, Dict2) -> Dict3</name> + <name name="merge" arity="3"/> <fsummary>Merge two dictionaries</fsummary> - <type> - <v>Fun = fun(Key, Value1, Value2) -> Value</v> - <v> Key = Value1 = Value2 = Value3 = term()</v> - <v>Dict1 = Dict2 = Dict3 = dictionary()</v> - </type> <desc> - <p><c>merge</c> merges two dictionaries, <c>Dict1</c> and - <c>Dict2</c>, to create a new dictionary. All the <c>Key</c> - - <c>Value</c> pairs from both dictionaries are included in + <p><c>merge</c> merges two dictionaries, <c><anno>Dict1</anno></c> and + <c><anno>Dict2</anno></c>, to create a new dictionary. All the <c><anno>Key</anno></c> + - <c><anno>Value</anno></c> pairs from both dictionaries are included in the new dictionary. If a key occurs in both dictionaries then - <c>Fun</c> is called with the key and both values to return a + <c><anno>Fun</anno></c> is called with the key and both values to return a new value. <c>merge</c> could be defined as:</p> <code type="none"> merge(Fun, D1, D2) -> @@ -219,75 +163,52 @@ merge(Fun, D1, D2) -> </desc> </func> <func> - <name>new() -> dictionary()</name> + <name name="new" arity="0"/> <fsummary>Create a dictionary</fsummary> <desc> <p>This function creates a new dictionary.</p> </desc> </func> <func> - <name>size(Dict) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of elements in a dictionary</fsummary> - <type> - <v>Dict = dictionary()</v> - </type> <desc> - <p>Returns the number of elements in a <c>Dict</c>.</p> + <p>Returns the number of elements in a <c><anno>Dict</anno></c>.</p> </desc> </func> <func> - <name>store(Key, Value, Dict1) -> Dict2</name> + <name name="store" arity="3"/> <fsummary>Store a value in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>This function stores a <c>Key</c> - <c>Value</c> pair in a - dictionary. If the <c>Key</c> already exists in <c>Dict1</c>, - the associated value is replaced by <c>Value</c>.</p> + <p>This function stores a <c><anno>Key</anno></c> - <c><anno>Value</anno></c> pair in a + dictionary. If the <c><anno>Key</anno></c> already exists in <c><anno>Dict1</anno></c>, + the associated value is replaced by <c><anno>Value</anno></c>.</p> </desc> </func> <func> - <name>to_list(Dict) -> List</name> + <name name="to_list" arity="1"/> <fsummary>Convert a dictionary to a list of pairs</fsummary> - <type> - <v>Dict = dictionary()</v> - <v>List = [{Key, Value}]</v> - </type> <desc> <p>This function converts the dictionary to a list representation.</p> </desc> </func> <func> - <name>update(Key, Fun, Dict1) -> Dict2</name> + <name name="update" arity="3"/> <fsummary>Update a value in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Fun = fun(Value1) -> Value2</v> - <v> Value1 = Value2 = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>Update a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on the value to get a new value. An exception is generated if - <c>Key</c> is not present in the dictionary.</p> + <c><anno>Key</anno></c> is not present in the dictionary.</p> </desc> </func> <func> - <name>update(Key, Fun, Initial, Dict1) -> Dict2</name> + <name name="update" arity="4"/> <fsummary>Update a value in a dictionary</fsummary> - <type> - <v>Key = Initial = term()</v> - <v>Fun = fun(Value1) -> Value2</v> - <v> Value1 = Value2 = term()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>Update a value in a dictionary by calling <c>Fun</c> on - the value to get a new value. If <c>Key</c> is not present - in the dictionary then <c>Initial</c> will be stored as + <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on + the value to get a new value. If <c><anno>Key</anno></c> is not present + in the dictionary then <c><anno>Initial</anno></c> will be stored as the first value. For example <c>append/3</c> could be defined as:</p> <code type="none"> @@ -296,17 +217,12 @@ append(Key, Val, D) -> </desc> </func> <func> - <name>update_counter(Key, Increment, Dict1) -> Dict2</name> + <name name="update_counter" arity="3"/> <fsummary>Increment a value in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Increment = number()</v> - <v>Dict1 = Dict2 = dictionary()</v> - </type> <desc> - <p>Add <c>Increment</c> to the value associated with <c>Key</c> - and store this value. If <c>Key</c> is not present in - the dictionary then <c>Increment</c> will be stored as + <p>Add <c><anno>Increment</anno></c> to the value associated with <c><anno>Key</anno></c> + and store this value. If <c><anno>Key</anno></c> is not present in + the dictionary then <c><anno>Increment</anno></c> will be stored as the first value.</p> <p>This could be defined as:</p> <code type="none"> diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml index ad256e671f..0afc70ebe0 100644 --- a/lib/stdlib/doc/src/digraph.xml +++ b/lib/stdlib/doc/src/digraph.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -87,67 +87,79 @@ is a digraph that has no cycles. </p> </description> + <datatypes> + <datatype> + <name name="d_type"/> + </datatype> + <datatype> + <name name="d_cyclicity"/> + </datatype> + <datatype> + <name name="d_protection"/> + </datatype> + <datatype> + <name><marker id="type-digraph">digraph()</marker></name> + <desc><p>A digraph as returned by <c>new/0,1</c>.</p></desc> + </datatype> + <datatype> + <name><marker id="type-edge">edge()</marker></name> + </datatype> + <datatype> + <name name="label"/> + </datatype> + <datatype> + <name><marker id="type-vertex">vertex()</marker></name> + </datatype> + </datatypes> <funcs> <func> - <name>add_edge(G, E, V1, V2, Label) -> edge() | {error, Reason}</name> - <name>add_edge(G, V1, V2, Label) -> edge() | {error, Reason}</name> - <name>add_edge(G, V1, V2) -> edge() | {error, Reason}</name> + <name name="add_edge" arity="3"/> + <name name="add_edge" arity="4"/> + <name name="add_edge" arity="5"/> <fsummary>Add an edge to a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>E = edge()</v> - <v>V1 = V2 = vertex()</v> - <v>Label = label()</v> - <v>Reason = {bad_edge, Path} | {bad_vertex, V}</v> - <v>Path = [vertex()]</v> - </type> + <type name="add_edge_err_rsn"/> <desc> - <p><c>add_edge/5</c> creates (or modifies) the edge <c>E</c> - of the digraph <c>G</c>, using <c>Label</c> as the (new) + <p><c>add_edge/5</c> creates (or modifies) the edge <c><anno>E</anno></c> + of the digraph <c><anno>G</anno></c>, using <c><anno>Label</anno></c> as the (new) <seealso marker="#label">label</seealso> of the edge. The edge is <seealso marker="#emanate">emanating</seealso> from - <c>V1</c> and <seealso marker="#incident">incident</seealso> - on <c>V2</c>. Returns <c>E</c>. + <c><anno>V1</anno></c> and <seealso marker="#incident">incident</seealso> + on <c><anno>V2</anno></c>. Returns <c><anno>E</anno></c>. </p> - <p><c>add_edge(G, V1, V2, Label)</c> is + <p><c>add_edge(<anno>G</anno>, <anno>V1</anno>, <anno>V2</anno>, <anno>Label</anno>)</c> is equivalent to - <c>add_edge(G, E, V1, V2, Label)</c>, - where <c>E</c> is a created edge. The created edge is + <c>add_edge(<anno>G</anno>, <anno>E</anno>, <anno>V1</anno>, <anno>V2</anno>, <anno>Label</anno>)</c>, + where <c><anno>E</anno></c> is a created edge. The created edge is represented by the term <c>['$e' | N]</c>, where N is an integer >= 0. </p> - <p><c>add_edge(G, V1, V2)</c> is equivalent to - <c>add_edge(G, V1, V2, [])</c>. + <p><c>add_edge(<anno>G</anno>, <anno>V1</anno>, <anno>V2</anno>)</c> is equivalent to + <c>add_edge(<anno>G</anno>, <anno>V1</anno>, <anno>V2</anno>, [])</c>. </p> <p>If the edge would create a cycle in an <seealso marker="#acyclic_digraph">acyclic digraph</seealso>, - then <c>{error, {bad_edge, Path}}</c> is returned. If - either of <c>V1</c> or <c>V2</c> is not a vertex of the - digraph <c>G</c>, then - <c>{error, {bad_vertex, </c>V<c>}}</c> is - returned, V = <c>V1</c> or - V = <c>V2</c>. + then <c>{error, {bad_edge, <anno>Path</anno>}}</c> is returned. If + either of <c><anno>V1</anno></c> or <c><anno>V2</anno></c> is not a vertex of the + digraph <c><anno>G</anno></c>, then + <c>{error, {bad_vertex, </c><anno>V</anno><c>}}</c> is + returned, <anno>V</anno> = <c><anno>V1</anno></c> or + <anno>V</anno> = <c><anno>V2</anno></c>. </p> </desc> </func> <func> - <name>add_vertex(G, V, Label) -> vertex()</name> - <name>add_vertex(G, V) -> vertex()</name> - <name>add_vertex(G) -> vertex()</name> + <name name="add_vertex" arity="1"/> + <name name="add_vertex" arity="2"/> + <name name="add_vertex" arity="3"/> <fsummary>Add or modify a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Label = label()</v> - </type> <desc> - <p><c>add_vertex/3</c> creates (or modifies) the vertex <c>V</c> - of the digraph <c>G</c>, using <c>Label</c> as the (new) + <p><c>add_vertex/3</c> creates (or modifies) the vertex <c><anno>V</anno></c> + of the digraph <c><anno>G</anno></c>, using <c><anno>Label</anno></c> as the (new) <seealso marker="#label">label</seealso> of the - vertex. Returns <c>V</c>. + vertex. Returns <c><anno>V</anno></c>. </p> - <p><c>add_vertex(G, V)</c> is equivalent to - <c>add_vertex(G, V, [])</c>. + <p><c>add_vertex(<anno>G</anno>, <anno>V</anno>)</c> is equivalent to + <c>add_vertex(<anno>G</anno>, <anno>V</anno>, [])</c>. </p> <p><c>add_vertex/1</c> creates a vertex using the empty list as label, and returns the created vertex. The created vertex @@ -157,304 +169,227 @@ </desc> </func> <func> - <name>del_edge(G, E) -> true</name> + <name name="del_edge" arity="2"/> <fsummary>Delete an edge from a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>E = edge()</v> - </type> <desc> - <p>Deletes the edge <c>E</c> from the digraph <c>G</c>. + <p>Deletes the edge <c><anno>E</anno></c> from the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>del_edges(G, Edges) -> true</name> + <name name="del_edges" arity="2"/> <fsummary>Delete edges from a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>Edges = [edge()]</v> - </type> <desc> - <p>Deletes the edges in the list <c>Edges</c> from the digraph - <c>G</c>. + <p>Deletes the edges in the list <c><anno>Edges</anno></c> from the digraph + <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>del_path(G, V1, V2) -> true</name> + <name name="del_path" arity="3"/> <fsummary>Delete paths from a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V1 = V2 = vertex()</v> - </type> <desc> - <p>Deletes edges from the digraph <c>G</c> until there are no + <p>Deletes edges from the digraph <c><anno>G</anno></c> until there are no <seealso marker="#path">paths</seealso> from the vertex - <c>V1</c> to the vertex <c>V2</c>. + <c><anno>V1</anno></c> to the vertex <c><anno>V2</anno></c>. </p> <p>A sketch of the procedure employed: Find an arbitrary <seealso marker="#simple_path">simple path</seealso> - v[1], v[2], ..., v[k] from <c>V1</c> to - <c>V2</c> in <c>G</c>. Remove all edges of - <c>G</c> <seealso marker="#emanate">emanating</seealso> from v[i] + v[1], v[2], ..., v[k] from <c><anno>V1</anno></c> to + <c><anno>V2</anno></c> in <c><anno>G</anno></c>. Remove all edges of + <c><anno>G</anno></c> <seealso marker="#emanate">emanating</seealso> from v[i] and <seealso marker="#incident">incident</seealso> to v[i+1] for 1 <= i < k (including multiple - edges). Repeat until there is no path between <c>V1</c> and - <c>V2</c>. + edges). Repeat until there is no path between <c><anno>V1</anno></c> and + <c><anno>V2</anno></c>. </p> </desc> </func> <func> - <name>del_vertex(G, V) -> true</name> + <name name="del_vertex" arity="2"/> <fsummary>Delete a vertex from a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - </type> <desc> - <p>Deletes the vertex <c>V</c> from the digraph <c>G</c>. Any + <p>Deletes the vertex <c><anno>V</anno></c> from the digraph <c><anno>G</anno></c>. Any edges <seealso marker="#emanate">emanating</seealso> from - <c>V</c> or <seealso marker="#incident">incident</seealso> - on <c>V</c> are also deleted. + <c><anno>V</anno></c> or <seealso marker="#incident">incident</seealso> + on <c><anno>V</anno></c> are also deleted. </p> </desc> </func> <func> - <name>del_vertices(G, Vertices) -> true</name> + <name name="del_vertices" arity="2"/> <fsummary>Delete vertices from a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> - <p>Deletes the vertices in the list <c>Vertices</c> from the - digraph <c>G</c>. + <p>Deletes the vertices in the list <c><anno>Vertices</anno></c> from the + digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>delete(G) -> true</name> + <name name="delete" arity="1"/> <fsummary>Delete a digraph.</fsummary> - <type> - <v>G = digraph()</v> - </type> <desc> - <p>Deletes the digraph <c>G</c>. This call is important - because digraphs are implemented with <c>Ets</c>. There is - no garbage collection of <c>Ets</c> tables. The digraph + <p>Deletes the digraph <c><anno>G</anno></c>. This call is important + because digraphs are implemented with <c>ETS</c>. There is + no garbage collection of <c>ETS</c> tables. The digraph will, however, be deleted if the process that created the digraph terminates. </p> </desc> </func> <func> - <name>edge(G, E) -> {E, V1, V2, Label} | false</name> + <name name="edge" arity="2"/> <fsummary>Return the vertices and the label of an edge of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>E = edge()</v> - <v>V1 = V2 = vertex()</v> - <v>Label = label()</v> - </type> <desc> - <p>Returns <c>{E, V1, V2, Label}</c> where - <c>Label</c> is the <seealso marker="#label">label</seealso> + <p>Returns <c>{<anno>E</anno>, <anno>V1</anno>, <anno>V2</anno>, <anno>Label</anno>}</c> where + <c><anno>Label</anno></c> is the <seealso marker="#label">label</seealso> of the edge - <c>E</c> <seealso marker="#emanate">emanating</seealso> from - <c>V1</c> and <seealso marker="#incident">incident</seealso> on - <c>V2</c> of the digraph <c>G</c>. - If there is no edge <c>E</c> of the - digraph <c>G</c>, then <c>false</c> is returned. + <c><anno>E</anno></c> <seealso marker="#emanate">emanating</seealso> from + <c><anno>V1</anno></c> and <seealso marker="#incident">incident</seealso> on + <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>. + If there is no edge <c><anno>E</anno></c> of the + digraph <c><anno>G</anno></c>, then <c>false</c> is returned. </p> </desc> </func> <func> - <name>edges(G) -> Edges</name> + <name name="edges" arity="1"/> <fsummary>Return all edges of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>Edges = [edge()]</v> - </type> <desc> - <p>Returns a list of all edges of the digraph <c>G</c>, in + <p>Returns a list of all edges of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> </func> <func> - <name>edges(G, V) -> Edges</name> + <name name="edges" arity="2"/> <fsummary>Return the edges emanating from or incident on a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Edges = [edge()]</v> - </type> <desc> <p>Returns a list of all edges <seealso marker="#emanate">emanating</seealso> from - or <seealso marker="#incident">incident</seealso> on <c>V</c> - of the digraph <c>G</c>, in some unspecified order.</p> + or <seealso marker="#incident">incident</seealso> on <c><anno>V</anno></c> + of the digraph <c><anno>G</anno></c>, in some unspecified order.</p> </desc> </func> <func> - <name>get_cycle(G, V) -> Vertices | false</name> + <name name="get_cycle" arity="2"/> <fsummary>Find one cycle in a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V1 = V2 = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>If there is a <seealso marker="#simple_cycle">simple cycle</seealso> of length two or more through the vertex - <c>V</c>, then the cycle is returned as a list - <c>[V, ..., V]</c> of vertices, otherwise if there + <c><anno>V</anno></c>, then the cycle is returned as a list + <c>[<anno>V</anno>, ..., <anno>V</anno>]</c> of vertices, otherwise if there is a <seealso marker="#loop">loop</seealso> through - <c>V</c>, then the loop is returned as a list <c>[V]</c>. If - there are no cycles through <c>V</c>, then <c>false</c> is + <c><anno>V</anno></c>, then the loop is returned as a list <c>[<anno>V</anno>]</c>. If + there are no cycles through <c><anno>V</anno></c>, then <c>false</c> is returned. </p> <p><c>get_path/3</c> is used for finding a simple cycle - through <c>V</c>. + through <c><anno>V</anno></c>. </p> </desc> </func> <func> - <name>get_path(G, V1, V2) -> Vertices | false</name> + <name name="get_path" arity="3"/> <fsummary>Find one path in a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V1 = V2 = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Tries to find a <seealso marker="#simple_path">simple path</seealso> from - the vertex <c>V1</c> to the vertex - <c>V2</c> of the digraph <c>G</c>. Returns the path as a - list <c>[V1, ..., V2]</c> of vertices, or - <c>false</c> if no simple path from <c>V1</c> to <c>V2</c> + the vertex <c><anno>V1</anno></c> to the vertex + <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>. Returns the path as a + list <c>[<anno>V1</anno>, ..., <anno>V2</anno>]</c> of vertices, or + <c>false</c> if no simple path from <c><anno>V1</anno></c> to <c><anno>V2</anno></c> of length one or more exists. </p> - <p>The digraph <c>G</c> is traversed in a depth-first manner, + <p>The digraph <c><anno>G</anno></c> is traversed in a depth-first manner, and the first path found is returned. </p> </desc> </func> <func> - <name>get_short_cycle(G, V) -> Vertices | false</name> + <name name="get_short_cycle" arity="2"/> <fsummary>Find one short cycle in a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V1 = V2 = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Tries to find an as short as possible <seealso marker="#simple_cycle">simple cycle</seealso> through - the vertex <c>V</c> of the digraph <c>G</c>. Returns the cycle - as a list <c>[V, ..., V]</c> of vertices, or - <c>false</c> if no simple cycle through <c>V</c> exists. + the vertex <c><anno>V</anno></c> of the digraph <c>G</c>. Returns the cycle + as a list <c>[<anno>V</anno>, ..., <anno>V</anno>]</c> of vertices, or + <c>false</c> if no simple cycle through <c><anno>V</anno></c> exists. Note that a <seealso marker="#loop">loop</seealso> through - <c>V</c> is returned as the list <c>[V, V]</c>. + <c><anno>V</anno></c> is returned as the list <c>[<anno>V</anno>, <anno>V</anno>]</c>. </p> <p><c>get_short_path/3</c> is used for finding a simple cycle - through <c>V</c>. + through <c><anno>V</anno></c>. </p> </desc> </func> <func> - <name>get_short_path(G, V1, V2) -> Vertices | false</name> + <name name="get_short_path" arity="3"/> <fsummary>Find one short path in a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V1 = V2 = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Tries to find an as short as possible <seealso marker="#simple_path">simple path</seealso> from - the vertex <c>V1</c> to the vertex <c>V2</c> of the digraph <c>G</c>. - Returns the path as a list <c>[V1, ..., V2]</c> of - vertices, or <c>false</c> if no simple path from <c>V1</c> - to <c>V2</c> of length one or more exists. + the vertex <c><anno>V1</anno></c> to the vertex <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>. + Returns the path as a list <c>[<anno>V1</anno>, ..., <anno>V2</anno>]</c> of + vertices, or <c>false</c> if no simple path from <c><anno>V1</anno></c> + to <c><anno>V2</anno></c> of length one or more exists. </p> - <p>The digraph <c>G</c> is traversed in a breadth-first + <p>The digraph <c><anno>G</anno></c> is traversed in a breadth-first manner, and the first path found is returned. </p> </desc> </func> <func> - <name>in_degree(G, V) -> integer()</name> + <name name="in_degree" arity="2"/> <fsummary>Return the in-degree of a vertex of a digraph.</fsummary> - <type> - <v>G= digraph()</v> - <v>V = vertex()</v> - </type> <desc> <p>Returns the <seealso marker="#in_degree">in-degree</seealso> of the vertex - <c>V</c> of the digraph <c>G</c>. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>in_edges(G, V) -> Edges</name> + <name name="in_edges" arity="2"/> <fsummary>Return all edges incident on a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Edges = [edge()]</v> - </type> <desc> <p>Returns a list of all edges <seealso marker="#incident">incident</seealso> on - <c>V</c> of the digraph <c>G</c>, in some unspecified order. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> </func> <func> - <name>in_neighbours(G, V) -> Vertices</name> + <name name="in_neighbours" arity="2"/> <fsummary>Return all in-neighbours of a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns a list of all <seealso marker="#in_neighbour">in-neighbours</seealso> of - <c>V</c> of the digraph <c>G</c>, in some unspecified order. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> </func> <func> - <name>info(G) -> InfoList</name> + <name name="info" arity="1"/> <fsummary>Return information about a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>InfoList = [{cyclicity, Cyclicity}, {memory, NoWords}, {protection, Protection}]</v> - <v>Cyclicity = cyclic | acyclic</v> - <v>Protection = protected | private</v> - <v>NoWords = integer() >= 0</v> - </type> + <type name="d_cyclicity"/> + <type name="d_protection"/> <desc> <p>Returns a list of <c>{Tag, Value}</c> pairs describing the - digraph <c>G</c>. The following pairs are returned: + digraph <c><anno>G</anno></c>. The following pairs are returned: </p> <list type="bulleted"> <item> - <p><c>{cyclicity, Cyclicity}</c>, where <c>Cyclicity</c> + <p><c>{cyclicity, <anno>Cyclicity</anno>}</c>, where <c><anno>Cyclicity</anno></c> is <c>cyclic</c> or <c>acyclic</c>, according to the options given to <c>new</c>.</p> </item> <item> - <p><c>{memory, NoWords}</c>, where <c>NoWords</c> is - the number of words allocated to the <c>ets</c> tables.</p> + <p><c>{memory, <anno>NoWords</anno>}</c>, where <c><anno>NoWords</anno></c> is + the number of words allocated to the <c>ETS</c> tables.</p> </item> <item> - <p><c>{protection, Protection}</c>, where <c>Protection</c> + <p><c>{protection, <anno>Protection</anno>}</c>, where <c><anno>Protection</anno></c> is <c>protected</c> or <c>private</c>, according to the options given to <c>new</c>.</p> </item> @@ -462,7 +397,7 @@ </desc> </func> <func> - <name>new() -> digraph()</name> + <name name="new" arity="0"/> <fsummary>Return a protected empty digraph, where cycles are allowed.</fsummary> <desc> <p>Equivalent to <c>new([])</c>. @@ -470,15 +405,16 @@ </desc> </func> <func> - <name>new(Type) -> digraph()</name> + <name name="new" arity="1"/> <fsummary>Create a new empty digraph.</fsummary> - <type> - <v>Type = [cyclic | acyclic | private | protected]</v> - </type> + <type variable="Type"/> + <type name="d_type"/> + <type name="d_cyclicity"/> + <type name="d_protection"/> <desc> <p>Returns an <seealso marker="#empty_digraph">empty digraph</seealso> with - properties according to the options in <c>Type</c>:</p> + properties according to the options in <c><anno>Type</anno></c>:</p> <taglist> <tag><c>cyclic</c></tag> <item>Allow <seealso marker="#cycle">cycles</seealso> in the @@ -491,101 +427,72 @@ <item>The digraph can be read and modified by the creating process only.</item> </taglist> - <p>If an unrecognized type option <c>T</c> is given or <c>Type</c> + <p>If an unrecognized type option <c>T</c> is given or <c><anno>Type</anno></c> is not a proper list, there will be a <c>badarg</c> exception. </p> </desc> </func> <func> - <name>no_edges(G) -> integer() >= 0</name> + <name name="no_edges" arity="1"/> <fsummary>Return the number of edges of the a digraph.</fsummary> - <type> - <v>G = digraph()</v> - </type> <desc> - <p>Returns the number of edges of the digraph <c>G</c>. + <p>Returns the number of edges of the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>no_vertices(G) -> integer() >= 0</name> + <name name="no_vertices" arity="1"/> <fsummary>Return the number of vertices of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - </type> <desc> - <p>Returns the number of vertices of the digraph <c>G</c>. + <p>Returns the number of vertices of the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>out_degree(G, V) -> integer()</name> + <name name="out_degree" arity="2"/> <fsummary>Return the out-degree of a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - </type> <desc> <p>Returns the <seealso marker="#out_degree">out-degree</seealso> of the vertex - <c>V</c> of the digraph <c>G</c>. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>out_edges(G, V) -> Edges</name> + <name name="out_edges" arity="2"/> <fsummary>Return all edges emanating from a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Edges = [edge()]</v> - </type> <desc> <p>Returns a list of all edges <seealso marker="#emanate">emanating</seealso> from - <c>V</c> of the digraph <c>G</c>, in some unspecified order. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> </func> <func> - <name>out_neighbours(G, V) -> Vertices</name> + <name name="out_neighbours" arity="2"/> <fsummary>Return all out-neighbours of a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns a list of all <seealso marker="#out_neighbour">out-neighbours</seealso> of - <c>V</c> of the digraph <c>G</c>, in some unspecified order. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> </func> <func> - <name>vertex(G, V) -> {V, Label} | false</name> + <name name="vertex" arity="2"/> <fsummary>Return the label of a vertex of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>V = vertex()</v> - <v>Label = label()</v> - </type> <desc> - <p>Returns <c>{V, Label}</c> where <c>Label</c> is the + <p>Returns <c>{<anno>V</anno>, <anno>Label</anno>}</c> where <c><anno>Label</anno></c> is the <seealso marker="#label">label</seealso> of the vertex - <c>V</c> of the digraph <c>G</c>, or <c>false</c> if there - is no vertex <c>V</c> of the digraph <c>G</c>. + <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, or <c>false</c> if there + is no vertex <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>. </p> </desc> </func> <func> - <name>vertices(G) -> Vertices</name> + <name name="vertices" arity="1"/> <fsummary>Return all vertices of a digraph.</fsummary> - <type> - <v>G = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> - <p>Returns a list of all vertices of the digraph <c>G</c>, in + <p>Returns a list of all vertices of the digraph <c><anno>G</anno></c>, in some unspecified order. </p> </desc> diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml index 4b137456b3..e44632bfd2 100644 --- a/lib/stdlib/doc/src/digraph_utils.xml +++ b/lib/stdlib/doc/src/digraph_utils.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2009</year> + <year>2000</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -119,49 +119,43 @@ considering all edges undirected.</p> </description> + <datatypes> + <datatype> + <name><marker id="type-digraph">digraph()</marker></name> + <desc><p>A digraph as returned by <c>digraph:new/0,1</c>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>arborescence_root(Digraph) -> no | {yes, Root}</name> + <name name="arborescence_root" arity="1"/> <fsummary>Check if a digraph is an arborescence.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Root = vertex()</v> - </type> <desc> - - <p>Returns <c>{yes, Root}</c> if <c>Root</c> is + <p>Returns <c>{yes, <anno>Root</anno>}</c> if <c><anno>Root</anno></c> is the <seealso marker="#root">root</seealso> of the arborescence - <c>Digraph</c>, <c>no</c> otherwise. + <c><anno>Digraph</anno></c>, <c>no</c> otherwise. </p> </desc> </func> <func> - <name>components(Digraph) -> [Component]</name> + <name name="components" arity="1"/> <fsummary>Return the components of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Component = [vertex()]</v> - </type> <desc> <p>Returns a list of <seealso marker="#components">connected components</seealso>. Each component is represented by its vertices. The order of the vertices and the order of the components are arbitrary. Each vertex of the digraph - <c>Digraph</c> occurs in exactly one component. + <c><anno>Digraph</anno></c> occurs in exactly one component. </p> </desc> </func> <func> - <name>condensation(Digraph) -> CondensedDigraph</name> + <name name="condensation" arity="1"/> <fsummary>Return a condensed graph of a digraph.</fsummary> - <type> - <v>Digraph = CondensedDigraph = digraph()</v> - </type> <desc> <p>Creates a digraph where the vertices are the <seealso marker="#strong_components">strongly connected - components</seealso> of <c>Digraph</c> as returned by + components</seealso> of <c><anno>Digraph</anno></c> as returned by <c>strong_components/1</c>. If X and Y are strongly connected components, and there exist vertices x and y in X and Y respectively such that there is an @@ -169,7 +163,7 @@ and <seealso marker="#incident">incident</seealso> on y, then an edge emanating from X and incident on Y is created. </p> - <p>The created digraph has the same type as <c>Digraph</c>. + <p>The created digraph has the same type as <c><anno>Digraph</anno></c>. All vertices and edges have the default <seealso marker="#label">label</seealso> <c>[]</c>. </p> @@ -181,12 +175,8 @@ </desc> </func> <func> - <name>cyclic_strong_components(Digraph) -> [StrongComponent]</name> + <name name="cyclic_strong_components" arity="1"/> <fsummary>Return the cyclic strong components of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>StrongComponent = [vertex()]</v> - </type> <desc> <p>Returns a list of <seealso marker="#strong_components">strongly connected components</seealso>. @@ -194,67 +184,50 @@ by its vertices. The order of the vertices and the order of the components are arbitrary. Only vertices that are included in some <seealso marker="#cycle">cycle</seealso> in - <c>Digraph</c> are returned, otherwise the returned list is + <c><anno>Digraph</anno></c> are returned, otherwise the returned list is equal to that returned by <c>strong_components/1</c>. </p> </desc> </func> <func> - <name>is_acyclic(Digraph) -> bool()</name> + <name name="is_acyclic" arity="1"/> <fsummary>Check if a digraph is acyclic.</fsummary> - <type> - <v>Digraph = digraph()</v> - </type> <desc> <p>Returns <c>true</c> if and only if the digraph - <c>Digraph</c> is <seealso marker="#acyclic_digraph">acyclic</seealso>.</p> + <c><anno>Digraph</anno></c> is <seealso marker="#acyclic_digraph">acyclic</seealso>.</p> </desc> </func> <func> - <name>is_arborescence(Digraph) -> bool()</name> + <name name="is_arborescence" arity="1"/> <fsummary>Check if a digraph is an arborescence.</fsummary> - <type> - <v>Digraph = digraph()</v> - </type> <desc> <p>Returns <c>true</c> if and only if the digraph - <c>Digraph</c> is + <c><anno>Digraph</anno></c> is an <seealso marker="#arborescence">arborescence</seealso>.</p> </desc> </func> <func> - <name>is_tree(Digraph) -> bool()</name> + <name name="is_tree" arity="1"/> <fsummary>Check if a digraph is a tree.</fsummary> - <type> - <v>Digraph = digraph()</v> - </type> <desc> <p>Returns <c>true</c> if and only if the digraph - <c>Digraph</c> is + <c><anno>Digraph</anno></c> is a <seealso marker="#tree">tree</seealso>.</p> </desc> </func> <func> - <name>loop_vertices(Digraph) -> Vertices</name> + <name name="loop_vertices" arity="1"/> <fsummary>Return the vertices of a digraph included in some loop.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> - <p>Returns a list of all vertices of <c>Digraph</c> that are + <p>Returns a list of all vertices of <c><anno>Digraph</anno></c> that are included in some <seealso marker="#loop">loop</seealso>.</p> </desc> </func> <func> - <name>postorder(Digraph) -> Vertices</name> + <name name="postorder" arity="1"/> <fsummary>Return the vertices of a digraph in post-order.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> - <p>Returns all vertices of the digraph <c>Digraph</c>. The + <p>Returns all vertices of the digraph <c><anno>Digraph</anno></c>. The order is given by a <seealso marker="#depth_first_traversal">depth-first traversal</seealso> of the digraph, collecting visited @@ -266,14 +239,10 @@ </desc> </func> <func> - <name>preorder(Digraph) -> Vertices</name> + <name name="preorder" arity="1"/> <fsummary>Return the vertices of a digraph in pre-order.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> - <p>Returns all vertices of the digraph <c>Digraph</c>. The + <p>Returns all vertices of the digraph <c><anno>Digraph</anno></c>. The order is given by a <seealso marker="#depth_first_traversal">depth-first traversal</seealso> of the digraph, collecting visited @@ -281,119 +250,94 @@ </desc> </func> <func> - <name>reachable(Vertices, Digraph) -> Vertices</name> + <name name="reachable" arity="2"/> <fsummary>Return the vertices reachable from some vertices of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns an unsorted list of digraph vertices such that for each vertex in the list, there is - a <seealso marker="#path">path</seealso> in <c>Digraph</c> from some - vertex of <c>Vertices</c> to the vertex. In particular, + a <seealso marker="#path">path</seealso> in <c><anno>Digraph</anno></c> from some + vertex of <c><anno>Vertices</anno></c> to the vertex. In particular, since paths may have length zero, the vertices of - <c>Vertices</c> are included in the returned list. + <c><anno>Vertices</anno></c> are included in the returned list. </p> </desc> </func> <func> - <name>reachable_neighbours(Vertices, Digraph) -> Vertices</name> + <name name="reachable_neighbours" arity="2"/> <fsummary>Return the neighbours reachable from some vertices of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns an unsorted list of digraph vertices such that for each vertex in the list, there is - a <seealso marker="#path">path</seealso> in <c>Digraph</c> of length - one or more from some vertex of <c>Vertices</c> to the + a <seealso marker="#path">path</seealso> in <c><anno>Digraph</anno></c> of length + one or more from some vertex of <c><anno>Vertices</anno></c> to the vertex. As a consequence, only those vertices - of <c>Vertices</c> that are included in + of <c><anno>Vertices</anno></c> that are included in some <seealso marker="#cycle">cycle</seealso> are returned. </p> </desc> </func> <func> - <name>reaching(Vertices, Digraph) -> Vertices</name> + <name name="reaching" arity="2"/> <fsummary>Return the vertices that reach some vertices of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a <seealso marker="#path">path</seealso> from the vertex to some - vertex of <c>Vertices</c>. In particular, since paths may have - length zero, the vertices of <c>Vertices</c> are included in + vertex of <c><anno>Vertices</anno></c>. In particular, since paths may have + length zero, the vertices of <c><anno>Vertices</anno></c> are included in the returned list. </p> </desc> </func> <func> - <name>reaching_neighbours(Vertices, Digraph) -> Vertices</name> + <name name="reaching_neighbours" arity="2"/> <fsummary>Return the neighbours that reach some vertices of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a <seealso marker="#path">path</seealso> of length one or more - from the vertex to some vertex of <c>Vertices</c>. As a consequence, - only those vertices of <c>Vertices</c> that are included in + from the vertex to some vertex of <c><anno>Vertices</anno></c>. As a consequence, + only those vertices of <c><anno>Vertices</anno></c> that are included in some <seealso marker="#cycle">cycle</seealso> are returned. </p> </desc> </func> <func> - <name>strong_components(Digraph) -> [StrongComponent]</name> + <name name="strong_components" arity="1"/> <fsummary>Return the strong components of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>StrongComponent = [vertex()]</v> - </type> <desc> <p>Returns a list of <seealso marker="#strong_components">strongly connected components</seealso>. Each strongly component is represented by its vertices. The order of the vertices and the order of the components are arbitrary. Each vertex of the digraph - <c>Digraph</c> occurs in exactly one strong component. + <c><anno>Digraph</anno></c> occurs in exactly one strong component. </p> </desc> </func> <func> - <name>subgraph(Digraph, Vertices [, Options]) -> Subgraph</name> + <name name="subgraph" arity="2"/> + <name name="subgraph" arity="3"/> <fsummary>Return a subgraph of a digraph.</fsummary> - <type> - <v>Digraph = Subgraph = digraph()</v> - <v>Options = [{type, SubgraphType}, {keep_labels, bool()}]</v> - <v>SubgraphType = inherit | type()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Creates a maximal <seealso marker="#subgraph">subgraph</seealso> of <c>Digraph</c> having - as vertices those vertices of <c>Digraph</c> that are - mentioned in <c>Vertices</c>. + as vertices those vertices of <c><anno>Digraph</anno></c> that are + mentioned in <c><anno>Vertices</anno></c>. </p> <p>If the value of the option <c>type</c> is <c>inherit</c>, - which is the default, then the type of <c>Digraph</c> is used + which is the default, then the type of <c><anno>Digraph</anno></c> is used for the subgraph as well. Otherwise the option value of <c>type</c> is used as argument to <c>digraph:new/1</c>. </p> <p>If the value of the option <c>keep_labels</c> is <c>true</c>, which is the default, then the <seealso marker="#label">labels</seealso> of vertices and edges - of <c>Digraph</c> are used for the subgraph as well. If the value + of <c><anno>Digraph</anno></c> are used for the subgraph as well. If the value is <c>false</c>, then the default label, <c>[]</c>, is used for the subgraph's vertices and edges. </p> - <p><c>subgraph(Digraph, Vertices)</c> is equivalent to - <c>subgraph(Digraph, Vertices, [])</c>. + <p><c>subgraph(<anno>Digraph</anno>, <anno>Vertices</anno>)</c> is equivalent to + <c>subgraph(<anno>Digraph</anno>, <anno>Vertices</anno>, [])</c>. </p> <p>There will be a <c>badarg</c> exception if any of the arguments are invalid. @@ -401,16 +345,12 @@ </desc> </func> <func> - <name>topsort(Digraph) -> Vertices | false</name> + <name name="topsort" arity="1"/> <fsummary>Return a topological sorting of the vertices of a digraph.</fsummary> - <type> - <v>Digraph = digraph()</v> - <v>Vertices = [vertex()]</v> - </type> <desc> <p>Returns a <seealso marker="#topsort">topological ordering</seealso> of the vertices of the digraph - <c>Digraph</c> if such an ordering exists, <c>false</c> + <c><anno>Digraph</anno></c> if such an ordering exists, <c>false</c> otherwise. For each vertex in the returned list, there are no <seealso marker="#out_neighbour">out-neighbours</seealso> that occur earlier in the list.</p> diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml index e6b48b270a..488499581f 100644 --- a/lib/stdlib/doc/src/epp.xml +++ b/lib/stdlib/doc/src/epp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -38,65 +38,61 @@ by <c>compile</c> to preprocess macros and include files before the actual parsing takes place.</p> </description> + <datatypes> + <datatype> + <name name="macros"></name> + </datatype> + <datatype> + <name name="epp_handle"></name> + <desc><p>Handle to the epp server.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>open(FileName, IncludePath) -> {ok,Epp} | {error, ErrorDescriptor}</name> - <name>open(FileName, IncludePath, PredefMacros) -> {ok,Epp} | {error, ErrorDescriptor}</name> + <name name="open" arity="2"/> + <name name="open" arity="3"/> <fsummary>Open a file for preprocessing</fsummary> - <type> - <v>FileName = atom() | string()</v> - <v>IncludePath = [DirectoryName]</v> - <v>DirectoryName = atom() | string()</v> - <v>PredefMacros = [{atom(),term()}]</v> - <v>Epp = pid() -- handle to the epp server</v> - <v>ErrorDescriptor = term()</v> - </type> <desc> <p>Opens a file for preprocessing.</p> </desc> </func> <func> - <name>close(Epp) -> ok</name> + <name name="close" arity="1"/> <fsummary>Close the preprocessing of the file associated with <c>Epp</c></fsummary> - <type> - <v>Epp = pid() -- handle to the epp server</v> - </type> <desc> <p>Closes the preprocessing of a file.</p> </desc> </func> <func> - <name>parse_erl_form(Epp) -> {ok, AbsForm} | {eof, Line} | {error, ErrorInfo}</name> + <name name="parse_erl_form" arity="1"/> <fsummary>Return the next Erlang form from the opened Erlang source file</fsummary> - <type> - <v>Epp = pid()</v> - <v>AbsForm = term()</v> - <v>Line = integer()</v> - <v>ErrorInfo = see separate description below.</v> - </type> <desc> <p>Returns the next Erlang form from the opened Erlang source file. - The tuple <c>{eof, Line}</c> is returned at end-of-file. The first + The tuple <c>{eof, <anno>Line</anno>}</c> is returned at end-of-file. The first form corresponds to an implicit attribute <c>-file(File,1).</c>, where <c>File</c> is the name of the file.</p> </desc> </func> <func> - <name>parse_file(FileName,IncludePath,PredefMacro) -> {ok,[Form]} | {error,OpenError}</name> - <fsummary>Preprocesse and parse an Erlang source file</fsummary> - <type> - <v>FileName = atom() | string()</v> - <v>IncludePath = [DirectoryName]</v> - <v>DirectoryName = atom() | string()</v> - <v>PredefMacros = [{atom(),term()}]</v> - <v>Form = term() -- same as returned by erl_parse:parse_form</v> - </type> + <name name="parse_file" arity="3"/> + <fsummary>Preprocess and parse an Erlang source file</fsummary> <desc> <p>Preprocesses and parses an Erlang source file. - Note that the tuple <c>{eof, Line}</c> returned at end-of-file is + Note that the tuple <c>{eof, <anno>Line</anno>}</c> returned at end-of-file is included as a "form".</p> </desc> </func> + <func> + <name name="format_error" arity="1"/> + <fsummary>Format an error descriptor</fsummary> + <desc> + <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns + a string which + describes the error or warning. This function is usually + called implicitly when processing an <c>ErrorInfo</c> + structure (see below).</p> + </desc> + </func> </funcs> <section> diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml index 62af23c5eb..d0622594d9 100644 --- a/lib/stdlib/doc/src/erl_eval.xml +++ b/lib/stdlib/doc/src/erl_eval.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -36,63 +36,108 @@ <description> <p>This module provides an interpreter for Erlang expressions. The expressions are in the abstract syntax as returned by - <c>erl_parse</c>, the Erlang parser, or a call to - <c>io:parse_erl_exprs/2</c>.</p> + <seealso marker="erl_parse"><c>erl_parse</c></seealso>, + the Erlang parser, or <seealso marker="io"> + <c>io</c></seealso>.</p> </description> + <datatypes> + <datatype> + <name name="bindings"/> + </datatype> + <datatype> + <name name="binding_struct"/> + <desc><p>A binding structure.</p></desc> + </datatype> + <datatype> + <name name="expression"/> + </datatype> + <datatype> + <name name="expressions"/> + <desc><p>As returned by <seealso marker="erl_parse#parse_exprs/1"> + <c>erl_parse:parse_exprs/1</c></seealso> or + <seealso marker="io#parse_erl_exprs/2"> + <c>io:parse_erl_exprs/2</c></seealso>.</p></desc> + </datatype> + <datatype> + <name name="expression_list"/> + </datatype> + <datatype> + <name name="func_spec"/> + </datatype> + <datatype> + <name name="lfun_eval_handler"/> + </datatype> + <datatype> + <name name="lfun_value_handler"/> + </datatype> + <datatype> + <name name="local_function_handler"/> + <desc><p>Further described + <seealso marker="#local_function_handler">below.</seealso></p> + </desc> + </datatype> + <datatype> + <name name="name"/> + </datatype> + <datatype> + <name name="nlfun_handler"/> + </datatype> + <datatype> + <name name="non_local_function_handler"/> + <desc><p>Further described + <seealso marker="#non_local_function_handler">below.</seealso></p> + </desc> + </datatype> + <datatype> + <name name="value"/> + </datatype> + </datatypes> <funcs> <func> - <name>exprs(Expressions, Bindings) -> {value, Value, NewBindings}</name> - <name>exprs(Expressions, Bindings, LocalFunctionHandler) -> {value, Value, NewBindings}</name> - <name>exprs(Expressions, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> {value, Value, NewBindings}</name> + <name name="exprs" arity="2"/> + <name name="exprs" arity="3"/> + <name name="exprs" arity="4"/> <fsummary>Evaluate expressions</fsummary> - <type> - <v>Expressions = as returned by erl_parse or io:parse_erl_exprs/2</v> - <v>Bindings = as returned by bindings/1</v> - <v>LocalFunctionHandler = {value, Func} | {eval, Func} | none</v> - <v>NonlocalFunctionHandler = {value, Func} | none</v> - </type> <desc> - <p>Evaluates <c>Expressions</c> with the set of bindings - <c>Bindings</c>, where <c>Expressions</c> is a sequence of + <p>Evaluates <c><anno>Expressions</anno></c> with the set of bindings + <c><anno>Bindings</anno></c>, where <c><anno>Expressions</anno></c> + is a sequence of expressions (in abstract syntax) of a type which may be - returned by <c>io:parse_erl_exprs/2</c>. See below for an + returned by <seealso marker="io#parse_erl_exprs/2"> + <c>io:parse_erl_exprs/2</c></seealso>. See below for an explanation of how and when to use the arguments - <c>LocalFunctionHandler</c> and <c>NonlocalFunctionHandler</c>. + <c><anno>LocalFunctionHandler</anno></c> and + <c><anno>NonLocalFunctionHandler</anno></c>. </p> - <p>Returns <c>{value, Value, NewBindings}</c></p> + <p>Returns <c>{value, <anno>Value</anno>, <anno>NewBindings</anno>}</c> + </p> </desc> </func> <func> - <name>expr(Expression, Bindings) -> { value, Value, NewBindings }</name> - <name>expr(Expression, Bindings, LocalFunctionHandler) -> { value, Value, NewBindings }</name> - <name>expr(Expression, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> { value, Value, NewBindings }</name> - <name>expr(Expression, Bindings, LocalFunctionHandler, NonlocalFunctionHandler, ReturnFormat) -> { value, Value, NewBindings } | Value</name> + <name name="expr" arity="2"/> + <name name="expr" arity="3"/> + <name name="expr" arity="4"/> + <name name="expr" arity="5"/> <fsummary>Evaluate expression</fsummary> - <type> - <v>Expression = as returned by io:parse_erl_form/2, for example</v> - <v>Bindings = as returned by bindings/1</v> - <v>LocalFunctionHandler = {value, Func} | {eval, Func} | none</v> - <v>NonlocalFunctionHandler = {value, Func} | none</v> - <v>ReturnFormat = value | none</v> - </type> <desc> - <p>Evaluates <c>Expression</c> with the set of bindings - <c>Bindings</c>. <c>Expression</c> is an expression (in - abstract syntax) of a type which may be returned by - <c>io:parse_erl_form/2</c>. See below for an explanation of + <p>Evaluates <c><anno>Expression</anno></c> with the set of bindings + <c><anno>Bindings</anno></c>. <c><anno>Expression</anno></c> + is an expression in + abstract syntax. See below for an explanation of how and when to use the arguments - <c>LocalFunctionHandler</c> and - <c>NonlocalFunctionHandler</c>. + <c><anno>LocalFunctionHandler</anno></c> and + <c><anno>NonLocalFunctionHandler</anno></c>. </p> - <p>Returns <c>{value, Value, NewBindings}</c> by default. But - if the <c>ReturnFormat</c> is <c>value</c> only the <c>Value</c> - is returned.</p> + <p>Returns <c>{value, <anno>Value</anno>, + <anno>NewBindings</anno>}</c> by default. But if the + <c><anno>ReturnFormat</anno></c> is <c>value</c> only + the <c><anno>Value</anno></c> is returned.</p> </desc> </func> <func> - <name>expr_list(ExpressionList, Bindings) -> {ValueList, NewBindings}</name> - <name>expr_list(ExpressionList, Bindings, LocalFunctionHandler) -> {ValueList, NewBindings}</name> - <name>expr_list(ExpressionList, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> {ValueList, NewBindings}</name> + <name name="expr_list" arity="2"/> + <name name="expr_list" arity="3"/> + <name name="expr_list" arity="4"/> <fsummary>Evaluate a list of expressions</fsummary> <desc> <p>Evaluates a list of expressions in parallel, using the same @@ -100,18 +145,19 @@ merge the bindings returned from each evaluation. This function is useful in the <c>LocalFunctionHandler</c>. See below. </p> - <p>Returns <c>{ValueList, NewBindings}</c>.</p> + <p>Returns <c>{<anno>ValueList</anno>, <anno>NewBindings</anno>}</c>. + </p> </desc> </func> <func> - <name>new_bindings() -> BindingStruct</name> + <name name="new_bindings" arity="0"/> <fsummary>Return a bindings structure</fsummary> <desc> <p>Returns an empty binding structure.</p> </desc> </func> <func> - <name>bindings(BindingStruct) -> Bindings</name> + <name name="bindings" arity="1"/> <fsummary>Return bindings</fsummary> <desc> <p>Returns the list of bindings contained in the binding @@ -119,25 +165,28 @@ </desc> </func> <func> - <name>binding(Name, BindingStruct) -> Binding</name> + <name name="binding" arity="2"/> <fsummary>Return bindings</fsummary> <desc> - <p>Returns the binding of <c>Name</c> in <c>BindingStruct</c>.</p> + <p>Returns the binding of <c><anno>Name</anno></c> + in <c><anno>BindingStruct</anno></c>.</p> </desc> </func> <func> - <name>add_binding(Name, Value, Bindings) -> BindingStruct</name> + <name name="add_binding" arity="3"/> <fsummary>Add a binding</fsummary> <desc> - <p>Adds the binding <c>Name = Value</c> to <c>Bindings</c>. + <p>Adds the binding <c><anno>Name</anno> = <anno>Value</anno></c> + to <c><anno>BindingStruct</anno></c>. Returns an updated binding structure.</p> </desc> </func> <func> - <name>del_binding(Name, Bindings) -> BindingStruct</name> + <name name="del_binding" arity="2"/> <fsummary>Delete a binding</fsummary> <desc> - <p>Removes the binding of <c>Name</c> in <c>Bindings</c>. + <p>Removes the binding of <c><anno>Name</anno></c> + in <c><anno>BindingStruct</anno></c>. Returns an updated binding structure.</p> </desc> </func> @@ -145,7 +194,8 @@ <section> <title>Local Function Handler</title> - <p>During evaluation of a function, no calls can be made to local + <p><marker id="local_function_handler"></marker> + During evaluation of a function, no calls can be made to local functions. An undefined function error would be generated. However, the optional argument <c>LocalFunctionHandler</c> may be used to define a function @@ -191,7 +241,8 @@ Func(Name, Arguments, Bindings) </code> <section> <title>Non-local Function Handler</title> - <p>The optional argument <c>NonlocalFunctionHandler</c> may be + <p><marker id="non_local_function_handler"></marker> + The optional argument <c>NonlocalFunctionHandler</c> may be used to define a function which is called in the following cases: a functional object (fun) is called; a built-in function is called; a function is called using the M:F syntax, where M diff --git a/lib/stdlib/doc/src/erl_expand_records.xml b/lib/stdlib/doc/src/erl_expand_records.xml index c93248493f..8ead438b31 100644 --- a/lib/stdlib/doc/src/erl_expand_records.xml +++ b/lib/stdlib/doc/src/erl_expand_records.xml @@ -39,12 +39,8 @@ </description> <funcs> <func> - <name>module(AbsForms, CompileOptions) -> AbsForms</name> + <name name="module" arity="2"/> <fsummary>Expand all records in a module</fsummary> - <type> - <v>AbsForms = [term()]</v> - <v>CompileOptions = [term()]</v> - </type> <desc> <p>Expands all records in a module. The returned module has no references to records, neither attributes nor code.</p> diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml index cfb18ec131..18cc2460f9 100644 --- a/lib/stdlib/doc/src/erl_id_trans.xml +++ b/lib/stdlib/doc/src/erl_id_trans.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1996</year> - <year>2010</year> + <year>2011</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -48,8 +48,8 @@ <name>parse_transform(Forms, Options) -> Forms</name> <fsummary>Transform Erlang forms</fsummary> <type> - <v>Forms = [erlang_form()]</v> - <v>Options = [compiler_options()]</v> + <v>Forms = [<seealso marker="erl_parse#type-abstract_form">erl_parse:abstract_form()</seealso>]</v> + <v>Options = [<seealso marker="compile#type-option">compile:option()</seealso>]</v> </type> <desc> <p>Performs an identity transformation on Erlang forms, as an example.</p> diff --git a/lib/stdlib/doc/src/erl_internal.xml b/lib/stdlib/doc/src/erl_internal.xml index 732d77c3ae..b8d5ad73b3 100644 --- a/lib/stdlib/doc/src/erl_internal.xml +++ b/lib/stdlib/doc/src/erl_internal.xml @@ -42,112 +42,75 @@ </description> <funcs> <func> - <name>bif(Name, Arity) -> bool()</name> + <name name="bif" arity="2"/> <fsummary>Test for an Erlang BIF</fsummary> - <type> - <v>Name = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Name/Arity</c> is an Erlang BIF + <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is an Erlang BIF which is automatically recognized by the compiler, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>guard_bif(Name, Arity) -> bool()</name> + <name name="guard_bif" arity="2"/> <fsummary>Test for an Erlang BIF allowed in guards</fsummary> - <type> - <v>Name = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Name/Arity</c> is an Erlang BIF + <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is an Erlang BIF which is allowed in guards, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>type_test(Name, Arity) -> bool()</name> + <name name="type_test" arity="2"/> <fsummary>Test for a valid type test</fsummary> - <type> - <v>Name = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Name/Arity</c> is a valid Erlang + <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is a valid Erlang type test, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>arith_op(OpName, Arity) -> bool()</name> + <name name="arith_op" arity="2"/> <fsummary>Test for an arithmetic operator</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>OpName/Arity</c> is an arithmetic + <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is an arithmetic operator, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>bool_op(OpName, Arity) -> bool()</name> + <name name="bool_op" arity="2"/> <fsummary>Test for a Boolean operator</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>OpName/Arity</c> is a Boolean + <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a Boolean operator, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>comp_op(OpName, Arity) -> bool()</name> + <name name="comp_op" arity="2"/> <fsummary>Test for a comparison operator</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>OpName/Arity</c> is a comparison + <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a comparison operator, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>list_op(OpName, Arity) -> bool()</name> + <name name="list_op" arity="2"/> <fsummary>Test for a list operator</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>OpName/Arity</c> is a list + <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a list operator, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>send_op(OpName, Arity) -> bool()</name> + <name name="send_op" arity="2"/> <fsummary>Test for a send operator</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>OpName/Arity</c> is a send + <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a send operator, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>op_type(OpName, Arity) -> Type</name> + <name name="op_type" arity="2"/> <fsummary>Return operator type</fsummary> - <type> - <v>OpName = atom()</v> - <v>Arity = integer()</v> - <v>Type = arith | bool | comp | list | send</v> - </type> <desc> - <p>Returns the <c>Type</c> of operator that <c>OpName/Arity</c> + <p>Returns the <c><anno>Type</anno></c> of operator that <c><anno>OpName</anno>/<anno>Arity</anno></c> belongs to, or generates a <c>function_clause</c> error if it is not an operator at all.</p> diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml index 8639d678fa..b7fbdd8799 100644 --- a/lib/stdlib/doc/src/erl_lint.xml +++ b/lib/stdlib/doc/src/erl_lint.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -60,29 +60,30 @@ functions separately unless you have written your own Erlang compiler.</p> </description> + <datatypes> + <datatype> + <name name="error_info"/> + </datatype> + <datatype> + <name name="error_description"/> + </datatype> + </datatypes> <funcs> <func> - <name>module(AbsForms) -> {ok,Warnings} | {error,Errors,Warnings}</name> - <name>module(AbsForms, FileName) -> {ok,Warnings} | {error,Errors,Warnings}</name> - <name>module(AbsForms, FileName, CompileOptions) -> {ok,Warnings} | {error,Errors,Warnings}</name> + <name name="module" arity="1"/> + <name name="module" arity="2"/> + <name name="module" arity="3"/> <fsummary>Check a module for errors</fsummary> - <type> - <v>AbsForms = [term()]</v> - <v>FileName = FileName2 = atom() | string()</v> - <v>Warnings = Errors = [{Filename2,[ErrorInfo]}]</v> - <v>ErrorInfo = see separate description below.</v> - <v>CompileOptions = [term()]</v> - </type> <desc> <p>This function checks all the forms in a module for errors. It returns: </p> <taglist> - <tag><c>{ok,Warnings}</c></tag> + <tag><c>{ok,<anno>Warnings</anno>}</c></tag> <item> <p>There were no errors in the module.</p> </item> - <tag><c>{error,Errors,Warnings}</c></tag> + <tag><c>{error,<anno>Errors</anno>,<anno>Warnings</anno>}</c></tag> <item> <p>There were errors in the module.</p> </item> @@ -93,14 +94,14 @@ elements of <c>Options</c> that control the warnings are only described in <seealso marker="compiler:compile#erl_lint_options">compile(3)</seealso>. </p> - <p>The <c>AbsForms</c> of a module which comes from a file + <p>The <c><anno>AbsForms</anno></c> of a module which comes from a file that is read through <c>epp</c>, the Erlang pre-processor, can come from many files. This means that any references to errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso>). The warnings and errors returned have the following format: </p> <code type="none"> - [{FileName2,[ErrorInfo]}] </code> + [{<anno>FileName2</anno>,[<anno>ErrorInfo</anno>]}] </code> <p>The errors and warnings are listed in the order in which they are encountered in the forms. This means that the errors from one file may be split into different entries in @@ -108,27 +109,20 @@ </desc> </func> <func> - <name>is_guard_test(Expr) -> bool()</name> + <name name="is_guard_test" arity="1"/> <fsummary>Test for a guard test</fsummary> - <type> - <v>Expr = term()</v> - </type> <desc> - <p>This function tests if <c>Expr</c> is a legal guard test. - <c>Expr</c> is an Erlang term representing the abstract form + <p>This function tests if <c><anno>Expr</anno></c> is a legal guard test. + <c><anno>Expr</anno></c> is an Erlang term representing the abstract form for the expression. <c>erl_parse:parse_exprs(Tokens)</c> can - be used to generate a list of <c>Expr</c>.</p> + be used to generate a list of <c><anno>Expr</anno></c>.</p> </desc> </func> <func> - <name>format_error(ErrorDescriptor) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Format an error descriptor</fsummary> - <type> - <v>ErrorDescriptor = errordesc()</v> - <v>Chars = [char() | Chars]</v> - </type> <desc> - <p>Takes an <c>ErrorDescriptor</c> and returns a string which + <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns a string which describes the error or warning. This function is usually called implicitly when processing an <c>ErrorInfo</c> structure (see below).</p> diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml index 18b592deea..bafc2e0746 100644 --- a/lib/stdlib/doc/src/erl_parse.xml +++ b/lib/stdlib/doc/src/erl_parse.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -36,31 +36,51 @@ <description> <p>This module is the basic Erlang parser which converts tokens into the abstract form of either forms (i.e., top-level constructs), - expressions, or terms. The Abstract Format is described in the ERTS - User's Guide. + expressions, or terms. The Abstract Format is described in the + <seealso marker="erts:absform">ERTS User's Guide</seealso>. Note that a token list must end with the <em>dot</em> token in order to be acceptable to the parse functions (see <seealso marker="erl_scan">erl_scan(3)</seealso>).</p> </description> + <datatypes> + <datatype> + <name name="abstract_clause"></name> + <desc><p>Parse tree for Erlang clause.</p> + </desc> + </datatype> + <datatype> + <name name="abstract_expr"></name> + <desc><p>Parse tree for Erlang expression.</p> + </desc> + </datatype> + <datatype> + <name name="abstract_form"></name> + <desc><p>Parse tree for Erlang form.</p> + </desc> + </datatype> + <datatype> + <name name="error_description"></name> + </datatype> + <datatype> + <name name="error_info"></name> + </datatype> + <datatype> + <name name="token"></name> + </datatype> + </datatypes> <funcs> <func> - <name>parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo}</name> + <name name="parse_form" arity="1"/> <fsummary>Parse an Erlang form</fsummary> - <type> - <v>Tokens = [Token]</v> - <v>Token = {Tag,Line} | {Tag,Line,term()}</v> - <v>Tag = atom()</v> - <v>AbsForm = term()</v> - <v>ErrorInfo = see section Error Information below.</v> - </type> <desc> - <p>This function parses <c>Tokens</c> as if it were a form. It returns:</p> + <p>This function parses <c><anno>Tokens</anno></c> as if it were + a form. It returns:</p> <taglist> - <tag><c>{ok, AbsForm}</c></tag> + <tag><c>{ok, <anno>AbsForm</anno>}</c></tag> <item> - <p>The parsing was successful. <c>AbsForm</c> is the + <p>The parsing was successful. <c><anno>AbsForm</anno></c> is the abstract form of the parsed form.</p> </item> - <tag><c>{error, ErrorInfo}</c></tag> + <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag> <item> <p>An error occurred.</p> </item> @@ -68,25 +88,18 @@ </desc> </func> <func> - <name>parse_exprs(Tokens) -> {ok, Expr_list} | {error, ErrorInfo}</name> + <name name="parse_exprs" arity="1"/> <fsummary>Parse Erlang expressions</fsummary> - <type> - <v>Tokens = [Token]</v> - <v>Token = {Tag,Line} | {Tag,Line,term()}</v> - <v>Tag = atom()</v> - <v>Expr_list = [AbsExpr]</v> - <v>AbsExpr = term()</v> - <v>ErrorInfo = see section Error Information below.</v> - </type> <desc> - <p>This function parses <c>Tokens</c> as if it were a list of expressions. It returns:</p> + <p>This function parses <c><anno>Tokens</anno></c> as if it were + a list of expressions. It returns:</p> <taglist> - <tag><c>{ok, Expr_list}</c></tag> + <tag><c>{ok, <anno>ExprList</anno>}</c></tag> <item> - <p>The parsing was successful. <c>Expr_list</c> is a + <p>The parsing was successful. <c><anno>ExprList</anno></c> is a list of the abstract forms of the parsed expressions.</p> </item> - <tag><c>{error, ErrorInfo}</c></tag> + <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag> <item> <p>An error occurred.</p> </item> @@ -94,21 +107,15 @@ </desc> </func> <func> - <name>parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo}</name> + <name name="parse_term" arity="1"/> <fsummary>Parse an Erlang term</fsummary> - <type> - <v>Tokens = [Token]</v> - <v>Token = {Tag,Line} | {Tag,Line,term()}</v> - <v>Tag = atom()</v> - <v>Term = term()</v> - <v>ErrorInfo = see section Error Information below.</v> - </type> <desc> - <p>This function parses <c>Tokens</c> as if it were a term. It returns:</p> + <p>This function parses <c><anno>Tokens</anno></c> as if it were + a term. It returns:</p> <taglist> - <tag><c>{ok, Term}</c></tag> + <tag><c>{ok, <anno>Term</anno>}</c></tag> <item> - <p>The parsing was successful. <c>Term</c> is + <p>The parsing was successful. <c><anno>Term</anno></c> is the Erlang term corresponding to the token list.</p> </item> <tag><c>{error, ErrorInfo}</c></tag> @@ -122,7 +129,8 @@ <name>format_error(ErrorDescriptor) -> Chars</name> <fsummary>Format an error descriptor</fsummary> <type> - <v>ErrorDescriptor = errordesc()</v> + <v>ErrorDescriptor = <seealso + marker="#type-error_info">error_description()</seealso></v> <v>Chars = [char() | Chars]</v> </type> <desc> @@ -133,44 +141,32 @@ </desc> </func> <func> - <name>tokens(AbsTerm) -> Tokens</name> - <name>tokens(AbsTerm, MoreTokens) -> Tokens</name> + <name name="tokens" arity="1"/> + <name name="tokens" arity="2"/> <fsummary>Generate a list of tokens for an expression</fsummary> - <type> - <v>Tokens = MoreTokens = [Token]</v> - <v>Token = {Tag,Line} | {Tag,Line,term()}</v> - <v>Tag = atom()</v> - <v>AbsTerm = term()</v> - <v>ErrorInfo = see section Error Information below.</v> - </type> <desc> <p>This function generates a list of tokens representing the abstract - form <c>AbsTerm</c> of an expression. Optionally, it appends - <c>Moretokens</c>.</p> + form <c><anno>AbsTerm</anno></c> of an expression. Optionally, it + appends <c><anno>MoreTokens</anno></c>.</p> </desc> </func> <func> - <name>normalise(AbsTerm) -> Data</name> + <name name="normalise" arity="1"/> <fsummary>Convert abstract form to an Erlang term</fsummary> - <type> - <v>AbsTerm = Data = term()</v> - </type> <desc> - <p>Converts the abstract form <c>AbsTerm</c> of a term into a + <p>Converts the abstract form <c><anno>AbsTerm</anno></c> of a + term into a conventional Erlang data structure (i.e., the term itself). This is the inverse of <c>abstract/1</c>.</p> </desc> </func> <func> - <name>abstract(Data) -> AbsTerm</name> + <name name="abstract" arity="1"/> <fsummary>Convert an Erlang term into an abstract form</fsummary> - <type> - <v>Data = AbsTerm = term()</v> - </type> <desc> - <p>Converts the Erlang data structure <c>Data</c> into an - abstract form of type <c>AbsTerm</c>. This is the inverse of - <c>normalise/1</c>.</p> + <p>Converts the Erlang data structure <c><anno>Data</anno></c> into an + abstract form of type <c><anno>AbsTerm</anno></c>. + This is the inverse of <c>normalise/1</c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml index 1fdda48893..57b5828bcd 100644 --- a/lib/stdlib/doc/src/erl_pp.xml +++ b/lib/stdlib/doc/src/erl_pp.xml @@ -43,93 +43,82 @@ <p>All functions can have an optional argument which specifies a hook that is called if an attempt is made to print an unknown form.</p> </description> + <datatypes> + <datatype> + <name name="hook_function"/> + <desc> + <p>The optional argument <marker id="hook_function"> + <c>HookFunction</c></marker>, shown in the functions described below, + defines a function which is called when an unknown form occurs where there + should be a valid expression.</p> + + <p>If <c>HookFunction</c> is equal to <c>none</c> there is no hook + function.</p> + + <p>The called hook function should return a (possibly deep) list + of characters. <seealso marker="#expr/4"><c>expr/4</c></seealso> + is useful in a hook. + </p> + <p>If <c><anno>CurrentIndentation</anno></c> is negative, there will be no line + breaks and only a space is used as a separator.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>form(Form) -> DeepCharList</name> - <name>form(Form, HookFunction) -> DeepCharList</name> + <name name="form" arity="1"/> + <name name="form" arity="2"/> <fsummary>Pretty print a form</fsummary> - <type> - <v>Form = term()</v> - <v>HookFunction = see separate description below.</v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>Pretty prints a - <c>Form</c> which is an abstract form of a type which is - returned by <c>erl_parse:parse_form</c>.</p> + <c><anno>Form</anno></c> which is an abstract form of a type which is + returned by <seealso marker="erl_parse#parse_form/1"> + <c>erl_parse:parse_form/1</c></seealso>.</p> </desc> </func> <func> - <name>attribute(Attribute) -> DeepCharList</name> - <name>attribute(Attribute, HookFunction) -> DeepCharList</name> + <name name="attribute" arity="1"/> + <name name="attribute" arity="2"/> <fsummary>Pretty print an attribute</fsummary> - <type> - <v>Attribute = term()</v> - <v>HookFunction = see separate description below.</v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>The same as <c>form</c>, but only for the attribute - <c>Attribute</c>.</p> + <c><anno>Attribute</anno></c>.</p> </desc> </func> <func> - <name>function(Function) -> DeepCharList</name> - <name>function(Function, HookFunction) -> DeepCharList</name> + <name name="function" arity="1"/> + <name name="function" arity="2"/> <fsummary>Pretty print a function</fsummary> - <type> - <v>Function = term()</v> - <v>HookFunction = see separate description below.</v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>The same as <c>form</c>, but only for the function - <c>Function</c>.</p> + <c><anno>Function</anno></c>.</p> </desc> </func> <func> - <name>guard(Guard) -> DeepCharList</name> - <name>guard(Guard, HookFunction) -> DeepCharList</name> + <name name="guard" arity="1"/> + <name name="guard" arity="2"/> <fsummary>Pretty print a guard</fsummary> - <type> - <v>Form = term()</v> - <v>HookFunction = see separate description below.</v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>The same as <c>form</c>, but only for the guard test - <c>Guard</c>.</p> + <c><anno>Guard</anno></c>.</p> </desc> </func> <func> - <name>exprs(Expressions) -> DeepCharList</name> - <name>exprs(Expressions, HookFunction) -> DeepCharList</name> - <name>exprs(Expressions, Indent, HookFunction) -> DeepCharList</name> + <name name="exprs" arity="1"/> + <name name="exprs" arity="2"/> + <name name="exprs" arity="3"/> <fsummary>Pretty print <c>Expressions</c></fsummary> - <type> - <v>Expressions = term()</v> - <v>HookFunction = see separate description below.</v> - <v>Indent = integer()</v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>The same as <c>form</c>, but only for the sequence of - expressions in <c>Expressions</c>.</p> + expressions in <c><anno>Expressions</anno></c>.</p> </desc> </func> <func> - <name>expr(Expression) -> DeepCharList</name> - <name>expr(Expression, HookFunction) -> DeepCharList</name> - <name>expr(Expression, Indent, HookFunction) -> DeepCharList</name> - <name>expr(Expression, Indent, Precedence, HookFunction) ->-> DeepCharList</name> + <name name="expr" arity="1"/> + <name name="expr" arity="2"/> + <name name="expr" arity="3"/> + <name name="expr" arity="4"/> <fsummary>Pretty print one <c>Expression</c></fsummary> - <type> - <v>Expression = term()</v> - <v>HookFunction = see separate description below.</v> - <v>Indent = integer()</v> - <v>Precedence = </v> - <v>DeepCharList = [char()|DeepCharList]</v> - </type> <desc> <p>This function prints one expression. It is useful for implementing hooks (see below).</p> </desc> @@ -137,32 +126,6 @@ </funcs> <section> - <title>Unknown Expression Hooks</title> - <p>The optional argument <c>HookFunction</c>, shown in the functions described above, defines a function which is called when an unknown form occurs where there - should be a valid expression. It can have the following formats:</p> - <taglist> - <tag><c>Function</c></tag> - <item> - <p>The hook function is called by:</p> - <code type="none"> -Function(Expr, - CurrentIndentation, - CurrentPrecedence, - HookFunction) </code> - </item> - <tag><c>none</c></tag> - <item> - <p>There is no hook function</p> - </item> - </taglist> - <p>The called hook function should return a (possibly deep) list - of characters. <c>expr/4</c> is useful in a hook. - </p> - <p>If <c>CurrentIndentation</c> is negative, there will be no line - breaks and only a space is used as a separator.</p> - </section> - - <section> <title>Bugs</title> <p>It should be possible to have hook functions for unknown forms at places other than expressions.</p> diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml index 1199c34f0f..54240dea19 100644 --- a/lib/stdlib/doc/src/erl_scan.xml +++ b/lib/stdlib/doc/src/erl_scan.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -37,56 +37,96 @@ <p>This module contains functions for tokenizing characters into Erlang tokens.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -category() = atom() -column() = integer() > 0 -line() = integer() -location() = line() | {line(), column()} -reserved_word_fun() -> fun(atom()) -> bool() -set_attribute_fun() -> fun(term()) -> term() -symbol() = atom() | float() | integer() | string() -token() = {category(), attributes()} | {category(), attributes(), symbol()} -attributes() = line() | list() | tuple()</code> - </section> + <datatypes> + <datatype> + <name name="attribute_info"></name> + </datatype> + <datatype> + <name name="attributes"></name> + </datatype> + <datatype> + <name name="attributes_data"></name> + </datatype> + <datatype> + <name name="category"></name> + </datatype> + <datatype> + <name name="column"></name> + </datatype> + <datatype> + <name name="error_description"></name> + </datatype> + <datatype> + <name name="error_info"></name> + </datatype> + <datatype> + <name name="info_line"></name> + </datatype> + <datatype> + <name name="info_location"></name> + </datatype> + <datatype> + <name name="line"></name> + </datatype> + <datatype> + <name name="location"></name> + </datatype> + <datatype> + <name name="option"></name> + </datatype> + <datatype> + <name name="options"></name> + </datatype> + <datatype> + <name name="symbol"></name> + </datatype> + <datatype> + <name name="resword_fun"></name> + </datatype> + <datatype> + <name name="token"></name> + </datatype> + <datatype> + <name name="token_info"></name> + </datatype> + <datatype> + <name name="tokens"></name> + </datatype> + <datatype> + <name name="tokens_result"></name> + </datatype> + </datatypes> <funcs> <func> - <name>string(String) -> Return</name> - <name>string(String, StartLocation) -> Return</name> - <name>string(String, StartLocation, Options) -> Return</name> + <name name="string" arity="1"/> + <name name="string" arity="2"/> + <name name="string" arity="3"/> <fsummary>Scan a string and return the Erlang tokens</fsummary> - <type> - <v>String = string()</v> - <v>Return = {ok, Tokens, EndLocation} | Error</v> - <v>Tokens = [token()]</v> - <v>Error = {error, ErrorInfo, EndLocation}</v> - <v>StartLocation = EndLocation = location()</v> - <v>Options = Option | [Option]</v> - <v>Option = {reserved_word_fun,reserved_word_fun()} - | return_comments | return_white_spaces | return - | text</v> - </type> <desc> - <p>Takes the list of characters <c>String</c> and tries to - scan (tokenize) them. Returns <c>{ok, Tokens, EndLocation}</c>, - where <c>Tokens</c> are the Erlang tokens from - <c>String</c>. <c>EndLocation</c> is the first location - after the last token.</p> - <p><c>{error, ErrorInfo, EndLocation}</c> is returned if an - error occurs. <c>EndLocation</c> is the first location after + <p>Takes the list of characters <c><anno>String</anno></c> and tries to + scan (tokenize) them. Returns <c>{ok, <anno>Tokens</anno>, + <anno>EndLocation</anno>}</c>, + where <c><anno>Tokens</anno></c> are the Erlang tokens from + <c><anno>String</anno></c>. <c><anno>EndLocation</anno></c> + is the first location after the last token.</p> + <p><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLocation</anno>}</c> + is returned if an error occurs. + <c><anno>ErrorLocation</anno></c> is the first location after the erroneous token.</p> - <p><c>string(String)</c> is equivalent to - <c>string(String, 1)</c>, and <c>string(String, - StartLocation)</c> is equivalent to <c>string(String, - StartLocation, [])</c>.</p> - <p><c>StartLocation</c> indicates the initial location when - scanning starts. If <c>StartLocation</c> is a line - <c>attributes()</c> as well as <c>EndLocation</c> and - <c>ErrorLocation</c> will be lines. If - <c>StartLocation</c> is a pair of a line and a column + <p><c>string(<anno>String</anno>)</c> is equivalent to + <c>string(<anno>String</anno>, 1)</c>, and + <c>string(<anno>String</anno>, + <anno>StartLocation</anno>)</c> is equivalent to + <c>string(<anno>String</anno>, + <anno>StartLocation</anno>, [])</c>.</p> + <p><c><anno>StartLocation</anno></c> indicates the initial location + when scanning starts. If <c><anno>StartLocation</anno></c> is a line + <c>attributes()</c> as well as <c><anno>EndLocation</anno></c> and + <c><anno>ErrorLocation</anno></c> will be lines. If + <c><anno>StartLocation</anno></c> is a pair of a line and a column <c>attributes()</c> takes the form of an opaque compound - data type, and <c>EndLocation</c> and <c>ErrorLocation</c> + data type, and <c><anno>EndLocation</anno></c> and + <c><anno>ErrorLocation</anno></c> will be pairs of a line and a column. The <em>token attributes</em> contain information about the column and the line where the token begins, as well as the text of the @@ -134,148 +174,130 @@ attributes() = line() | list() | tuple()</code> </desc> </func> <func> - <name>tokens(Continuation, CharSpec, StartLocation) -> Return</name> - <name>tokens(Continuation, CharSpec, StartLocation, Options) -> Return</name> + <name name="tokens" arity="3"/> + <name name="tokens" arity="4"/> + <type name="char_spec"/> + <type name="return_cont"/> + <type_desc name="return_cont">An opaque continuation</type_desc> <fsummary>Re-entrant scanner</fsummary> - <type> - <v>Continuation = [] | Continuation1</v> - <v>Return = {done, Result, LeftOverChars} | {more, Continuation1}</v> - <v>LeftOverChars = CharSpec</v> - <v>CharSpec = string() | eof</v> - <v>Continuation1 = tuple()</v> - <v>Result = {ok, Tokens, EndLocation} | {eof, EndLocation} | Error</v> - <v>Tokens = [token()]</v> - <v>Error = {error, ErrorInfo, EndLocation}</v> - <v>StartLocation = EndLocation = location()</v> - <v>Options = Option | [Option]</v> - <v>Option = {reserved_word_fun,reserved_word_fun()} - | return_comments | return_white_spaces | return - | text</v> - </type> <desc> <p>This is the re-entrant scanner which scans characters until a <em>dot</em> ('.' followed by a white space) or <c>eof</c> has been reached. It returns:</p> <taglist> - <tag><c>{done, Result, LeftOverChars}</c></tag> + <tag><c>{done, <anno>Result</anno>, <anno>LeftOverChars</anno>}</c> + </tag> <item> <p>This return indicates that there is sufficient input - data to get a result. <c>Result</c> is:</p> + data to get a result. <c><anno>Result</anno></c> is:</p> <taglist> - <tag><c>{ok, Tokens, EndLocation}</c></tag> + <tag><c>{ok, Tokens, EndLocation}</c> + </tag> <item> - <p>The scanning was successful. <c>Tokens</c> is the - list of tokens including <em>dot</em>.</p> + <p>The scanning was successful. <c>Tokens</c> + is the list of tokens including <em>dot</em>.</p> </item> <tag><c>{eof, EndLocation}</c></tag> <item> <p>End of file was encountered before any more tokens.</p> </item> - <tag><c>{error, ErrorInfo, EndLocation}</c></tag> + <tag><c>{error, ErrorInfo, EndLocation}</c> + </tag> <item> - <p>An error occurred. <c>LeftOverChars</c> is the remaining - characters of the input data, + <p>An error occurred. <c><anno>LeftOverChars</anno></c> + is the remaining characters of the input data, starting from <c>EndLocation</c>.</p> </item> </taglist> </item> - <tag><c>{more, Continuation1}</c></tag> + <tag><c>{more, <anno>Continuation1</anno>}</c></tag> <item> <p>More data is required for building a term. - <c>Continuation1</c> must be passed in a new call to + <c><anno>Continuation1</anno></c> must be passed in a new call to <c>tokens/3,4</c> when more data is available.</p> </item> </taglist> - <p>The <c>CharSpec</c> <c>eof</c> signals end of file. - <c>LeftOverChars</c> will then take the value <c>eof</c> as - well.</p> - <p><c>tokens(Continuation, CharSpec, StartLocation)</c> is - equivalent to <c>tokens(Continuation, CharSpec, - StartLocation, [])</c>.</p> + <p>The <c><anno>CharSpec</anno></c> <c>eof</c> signals end of file. + <c><anno>LeftOverChars</anno></c> will then take the value <c>eof</c> + as well.</p> + <p><c>tokens(<anno>Continuation</anno>, <anno>CharSpec</anno>, + <anno>StartLocation</anno>)</c> is equivalent to + <c>tokens(<anno>Continuation</anno>, <anno>CharSpec</anno>, + <anno>StartLocation</anno>, [])</c>.</p> <p>See <seealso marker="#string/3">string/3</seealso> for a description of the various options.</p> </desc> </func> <func> - <name>reserved_word(Atom) -> bool()</name> + <name name="reserved_word" arity="1"/> <fsummary>Test for a reserved word</fsummary> - <type> - <v>Atom = atom()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Atom</c> is an Erlang reserved - word, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Atom</anno></c> is an Erlang + reserved word, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>token_info(Token) -> TokenInfo</name> + <name name="token_info" arity="1"/> <fsummary>Return information about a token</fsummary> - <type> - <v>Token = token()</v> - <v>TokenInfo = [TokenInfoTuple]</v> - <v>TokenInfoTuple = {TokenItem, Info}</v> - <v>TokenItem = atom()</v> - <v>Info = term()</v> - </type> <desc> <p>Returns a list containing information about the token - <c>Token</c>. The order of the <c>TokenInfoTuple</c>s is not - defined. The following <c>TokenItem</c>s are returned: - <c>category</c>, <c>column</c>, <c>length</c>, - <c>line</c>, <c>symbol</c>, and <c>text</c>. See <seealso + <c><anno>Token</anno></c>. The order of the + <c><anno>TokenInfoTuple</anno></c>s is not + defined. See <seealso marker="#token_info/2">token_info/2</seealso> for information about specific - <c>TokenInfoTuple</c>s.</p> + <c><anno>TokenInfoTuple</anno></c>s.</p> <p>Note that if <c>token_info(Token, TokenItem)</c> returns - <c>undefined</c> for some <c>TokenItem</c> in the list above, the - item is not included in <c>TokenInfo</c>.</p> + <c>undefined</c> for some <c>TokenItem</c>, the + item is not included in <c><anno>TokenInfo</anno></c>.</p> </desc> </func> <func> - <name>token_info(Token, TokenItemSpec) -> TokenInfo</name> + <name name="token_info" arity="2" clause_i="1"/> + <name name="token_info" arity="2" clause_i="2"/> + <type name="token_item"/> + <type name="attribute_item"/> <fsummary>Return information about a token</fsummary> - <type> - <v>Token = token()</v> - <v>TokenItemSpec = TokenItem | [TokenItem]</v> - <v>TokenInfo = TokenInfoTuple | undefined | [TokenInfoTuple]</v> - <v>TokenInfoTuple = {TokenItem, Info}</v> - <v>TokenItem = atom()</v> - <v>Info = term()</v> - </type> <desc> <p>Returns a list containing information about the token - <c>Token</c>. If <c>TokenItemSpec</c> is a single - <c>TokenItem</c>, the returned value is the corresponding + <c><anno>Token</anno></c>. If one single + <c><anno>TokenItem</anno></c> is given the returned value is + the corresponding <c>TokenInfoTuple</c>, or <c>undefined</c> if the - <c>TokenItem</c> has no value. If <c>TokenItemSpec</c> is a - list of - <c>TokenItem</c>, the result is a list of - <c>TokenInfoTuple</c>. The <c>TokenInfoTuple</c>s will - appear with the corresponding - <c>TokenItem</c>s in the same order as the <c>TokenItem</c>s - appeared in the list of <c>TokenItem</c>s. <c>TokenItem</c>s - with no value are not included in the list of - <c>TokenInfoTuple</c>.</p> - <p>The following <c>TokenInfoTuple</c>s with corresponding - <c>TokenItem</c>s are valid:</p> + <c>TokenItem</c> has no value. If a list of + <c><anno>TokenItem</anno></c>s is given the result is a list of + <c><anno>TokenInfoTuple</anno></c>. The + <c><anno>TokenInfoTuple</anno></c>s will + appear with the corresponding <c><anno>TokenItem</anno></c>s in + the same order as the <c><anno>TokenItem</anno></c>s + appear in the list of <c>TokenItem</c>s. + <c><anno>TokenItem</anno></c>s with no value are not included + in the list of <c><anno>TokenInfoTuple</anno></c>.</p> + <p>The following <c><anno>TokenInfoTuple</anno></c>s with corresponding + <c><anno>TokenItem</anno></c>s are valid:</p> <taglist> - <tag><c>{category, category()}</c></tag> + <tag><c>{category, <seealso marker="#type-category"> + category()</seealso>}</c></tag> <item><p>The category of the token.</p> </item> - <tag><c>{column, column()}</c></tag> + <tag><c>{column, <seealso marker="#type-column"> + column()</seealso>}</c></tag> <item><p>The column where the token begins.</p> </item> <tag><c>{length, integer() > 0}</c></tag> <item><p>The length of the token's text.</p> </item> - <tag><c>{line, line()}</c></tag> + <tag><c>{line, <seealso marker="#type-line"> + line()</seealso>}</c></tag> <item><p>The line where the token begins.</p> </item> - <tag><c>{location, location()}</c></tag> + <tag><c>{location, <seealso marker="#type-location"> + location()</seealso>}</c></tag> <item><p>The line and column where the token begins, or just the line if the column unknown.</p> </item> - <tag><c>{symbol, symbol()}</c></tag> + <tag><c>{symbol, <seealso marker="#type-symbol"> + symbol()</seealso>}</c></tag> <item><p>The token's symbol.</p> </item> <tag><c>{text, string()}</c></tag> @@ -285,70 +307,59 @@ attributes() = line() | list() | tuple()</code> </desc> </func> <func> - <name>attributes_info(Attributes) -> AttributesInfo</name> + <name name="attributes_info" arity="1"/> <fsummary>Return information about token attributes</fsummary> - <type> - <v>Attributes = attributes()</v> - <v>AttributesInfo = [AttributeInfoTuple]</v> - <v>AttributeInfoTuple = {AttributeItem, Info}</v> - <v>AttributeItem = atom()</v> - <v>Info = term()</v> - </type> <desc> <p>Returns a list containing information about the token - attributes <c>Attributes</c>. The order of the - <c>AttributeInfoTuple</c>s is not defined. The following - <c>AttributeItem</c>s are returned: - <c>column</c>, <c>length</c>, <c>line</c>, and <c>text</c>. + attributes <c><anno>Attributes</anno></c>. The order of the + <c><anno>AttributeInfoTuple</anno></c>s is not defined. See <seealso marker="#attributes_info/2">attributes_info/2</seealso> for information about specific - <c>AttributeInfoTuple</c>s.</p> + <c><anno>AttributeInfoTuple</anno></c>s.</p> <p>Note that if <c>attributes_info(Token, AttributeItem)</c> returns <c>undefined</c> for some <c>AttributeItem</c> in the list above, the item is not included in - <c>AttributesInfo</c>.</p> + <c><anno>AttributesInfo</anno></c>.</p> </desc> </func> <func> - <name>attributes_info(Attributes, AttributeItemSpec) -> AttributesInfo</name> + <name name="attributes_info" arity="2" clause_i="1"/> + <name name="attributes_info" arity="2" clause_i="2"/> <fsummary>Return information about a token attributes</fsummary> - <type> - <v>Attributes = attributes()</v> - <v>AttributeItemSpec = AttributeItem | [AttributeItem]</v> - <v>AttributesInfo = AttributeInfoTuple | undefined - | [AttributeInfoTuple]</v> - <v>AttributeInfoTuple = {AttributeItem, Info}</v> - <v>AttributeItem = atom()</v> - <v>Info = term()</v> - </type> + <type name="attribute_item"/> <desc> <p>Returns a list containing information about the token - attributes <c>Attributes</c>. If <c>AttributeItemSpec</c> is - a single <c>AttributeItem</c>, the returned value is the - corresponding <c>AttributeInfoTuple</c>, or <c>undefined</c> - if the <c>AttributeItem</c> has no value. If - <c>AttributeItemSpec</c> is a list of - <c>AttributeItem</c>, the result is a list of - <c>AttributeInfoTuple</c>. The <c>AttributeInfoTuple</c>s - will appear with the corresponding <c>AttributeItem</c>s in - the same order as the <c>AttributeItem</c>s appeared in the - list of <c>AttributeItem</c>s. <c>AttributeItem</c>s with no + attributes <c><anno>Attributes</anno></c>. If one single + <c><anno>AttributeItem</anno></c> is given the returned value is the + corresponding <c><anno>AttributeInfoTuple</anno></c>, + or <c>undefined</c> if the <c><anno>AttributeItem</anno></c> + has no value. If a list of <c><anno>AttributeItem</anno></c> + is given the result is a list of + <c><anno>AttributeInfoTuple</anno></c>. + The <c><anno>AttributeInfoTuple</anno></c>s + will appear with the corresponding <c><anno>AttributeItem</anno></c>s + in the same order as the <c><anno>AttributeItem</anno></c>s + appear in the list of <c><anno>AttributeItem</anno></c>s. + <c><anno>AttributeItem</anno></c>s with no value are not included in the list of - <c>AttributeInfoTuple</c>.</p> - <p>The following <c>AttributeInfoTuple</c>s with corresponding - <c>AttributeItem</c>s are valid:</p> + <c><anno>AttributeInfoTuple</anno></c>.</p> + <p>The following <c><anno>AttributeInfoTuple</anno></c>s with + corresponding <c><anno>AttributeItem</anno></c>s are valid:</p> <taglist> - <tag><c>{column, column()}</c></tag> + <tag><c>{column, <seealso marker="#type-column"> + column()</seealso>}</c></tag> <item><p>The column where the token begins.</p> </item> <tag><c>{length, integer() > 0}</c></tag> <item><p>The length of the token's text.</p> </item> - <tag><c>{line, line()}</c></tag> + <tag><c>{line, <seealso marker="#type-line"> + line()</seealso>}</c></tag> <item><p>The line where the token begins.</p> </item> - <tag><c>{location, location()}</c></tag> + <tag><c>{location, <seealso marker="#type-location"> + location()</seealso>}</c></tag> <item><p>The line and column where the token begins, or just the line if the column unknown.</p> </item> @@ -359,29 +370,22 @@ attributes() = line() | list() | tuple()</code> </desc> </func> <func> - <name>set_attribute(AttributeItem, Attributes, SetAttributeFun) -> AttributesInfo</name> + <name name="set_attribute" arity="3"/> <fsummary>Set a token attribute value</fsummary> - <type> - <v>AttributeItem = line</v> - <v>Attributes = attributes()</v> - <v>SetAttributeFun = set_attribute_fun()</v> - </type> <desc> <p>Sets the value of the <c>line</c> attribute of the token - attributes <c>Attributes</c>.</p> - <p>The <c>SetAttributeFun</c> is called with the value of + attributes <c><anno>Attributes</anno></c>.</p> + <p>The <c><anno>SetAttributeFun</anno></c> is called with the value of the <c>line</c> attribute, and is to return the new value of the <c>line</c> attribute.</p> </desc> </func> <func> - <name>format_error(ErrorDescriptor) -> string()</name> + <name name="format_error" arity="1"/> <fsummary>Format an error descriptor</fsummary> - <type> - <v>ErrorDescriptor = errordesc()</v> - </type> <desc> - <p>Takes an <c>ErrorDescriptor</c> and returns a string which + <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns + a string which describes the error or warning. This function is usually called implicitly when processing an <c>ErrorInfo</c> structure (see below).</p> diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml index 929620bb88..fe166dbd01 100644 --- a/lib/stdlib/doc/src/erl_tar.xml +++ b/lib/stdlib/doc/src/erl_tar.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2003</year><year>2009</year> + <year>2003</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -89,9 +89,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="add"></marker> -<c>add/3</c> function adds a file to a tar file - that has been opened for writing by + <p>The <marker id="add"></marker><c>add/3</c> function adds + a file to a tar file that has been opened for writing by <seealso marker="#open">open/1</seealso>.</p> <taglist> <tag><c>dereference</c></tag> @@ -138,8 +137,8 @@ <v>TarDescriptor = term()</v> </type> <desc> - <p>The <marker id="close"></marker> -<c>close/1</c> function closes a tar file + <p>The <marker id="close"></marker><c>close/1</c> function + closes a tar file opened by <seealso marker="#open">open/1</seealso>.</p> </desc> </func> @@ -151,11 +150,12 @@ <v>FileList = [Filename|{NameInArchive, binary()},{NameInArchive, Filename}]</v> <v>Filename = filename()</v> <v>NameInArchive = filename()</v> - <v>RetValue = ok|{error,{Name,Reason}} <V>Reason = term()</v> + <v>RetValue = ok|{error,{Name,Reason}}</v> + <v>Reason = term()</v> </type> <desc> - <p>The <marker id="create_2"></marker> -<c>create/2</c> function creates a tar file and + <p>The <marker id="create_2"></marker><c>create/2</c> function + creates a tar file and archives the files whose names are given in <c>FileList</c> into it. The files may either be read from disk or given as binaries.</p> @@ -171,11 +171,11 @@ <v>NameInArchive = filename()</v> <v>OptionList = [Option]</v> <v>Option = compressed|cooked|dereference|verbose</v> - <v>RetValue = ok|{error,{Name,Reason}} <V>Reason = term()</v> + <v>RetValue = ok|{error,{Name,Reason}}</v> + <v>Reason = term()</v> </type> <desc> - <p>The <marker id="create_3"></marker> -<c>create/3</c> function + <p>The <marker id="create_3"></marker><c>create/3</c> function creates a tar file and archives the files whose names are given in <c>FileList</c> into it. The files may either be read from disk or given as binaries.</p> @@ -220,9 +220,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="extract_1"></marker> -<c>extract/1</c> function extracts - all files from a tar archive.</p> + <p>The <marker id="extract_1"></marker><c>extract/1</c> function + extracts all files from a tar archive.</p> <p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>", the contents of the binary is assumed to be a tar archive. </p> @@ -250,9 +249,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="extract_2"></marker> -<c>extract/2</c> function extracts - files from a tar archive.</p> + <p>The <marker id="extract_2"></marker><c>extract/2</c> function + extracts files from a tar archive.</p> <p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>", the contents of the binary is assumed to be a tar archive. </p> @@ -322,8 +320,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="format_error_1"></marker> -<c>format_error/1</c> converts + <p>The <marker id="format_error_1"></marker><c>format_error/1</c> + function converts an error reason term to a human-readable error message string.</p> </desc> </func> @@ -339,8 +337,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="open"></marker> -<c>open/2</c> function creates a tar file for writing. + <p>The <marker id="open"></marker><c>open/2</c> function creates + a tar file for writing. (Any existing file with the same name will be truncated.)</p> <p>By convention, the name of a tar file should end in "<c>.tar</c>". To abide to the convention, you'll need to add "<c>.tar</c>" yourself @@ -373,7 +371,6 @@ You should not rely on the specific contents of the <c>TarDescriptor</c> term, as it may change in future versions as more features are added to the <c>erl_tar</c> module.</p> - <p></p> </warning> </desc> </func> @@ -386,9 +383,8 @@ <v>Reason = term()</v> </type> <desc> - <p>The <marker id="table_1"></marker> -<c>table/1</c> function retrieves - the names of all files in the tar file <c>Name</c>.</p> + <p>The <marker id="table_1"></marker><c>table/1</c> function + retrieves the names of all files in the tar file <c>Name</c>.</p> </desc> </func> <func> @@ -398,9 +394,8 @@ <v>Name = filename()</v> </type> <desc> - <p>The <marker id="table_2"></marker> -<c>table/2</c> function retrieves - the names of all files in the tar file <c>Name</c>.</p> + <p>The <marker id="table_2"></marker><c>table/2</c> function + retrieves the names of all files in the tar file <c>Name</c>.</p> </desc> </func> <func> @@ -410,8 +405,7 @@ <v>Name = filename()</v> </type> <desc> - <p>The <marker id="t_1"></marker> -<c>t/1</c> function prints the names + <p>The <marker id="t_1"></marker><c>t/1</c> function prints the names of all files in the tar file <c>Name</c> to the Erlang shell. (Similar to "<c>tar t</c>".)</p> </desc> @@ -423,8 +417,8 @@ <v>Name = filename()</v> </type> <desc> - <p>The <marker id="tt_1"></marker> -<c>tt/1</c> function prints names and + <p>The <marker id="tt_1"></marker><c>tt/1</c> function prints + names and information about all files in the tar file <c>Name</c> to the Erlang shell. (Similar to "<c>tar tv</c>".)</p> </desc> diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index 746f94d3f4..efd9514db6 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -126,15 +126,30 @@ <em>ERTS User's Guide</em>.</p> </section> - <section> - <title>DATA TYPES</title> - <code type="none"> -match_spec() - a match specification, see above - -tid() - a table identifier, as returned by new/2</code> - </section> + <datatypes> + <datatype> + <name><marker id="type-continuation">continuation()</marker></name> + <desc> + <p>Opaque continuation used by <seealso marker="#select/1"> + <c>select/1</c></seealso> and <seealso marker="#select/3"> + <c>select/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="match_spec"/> + <desc><p>A match specification, see above.</p></desc> + </datatype> + <datatype> + <name name="match_pattern"/> + </datatype> + <datatype> + <name name="tab"/> + </datatype> + <datatype> + <name name="tid"/> + <desc><p>A table identifier, as returned by new/2.</p></desc> + </datatype> + </datatypes> <funcs> <func> <name>all() -> [Tab]</name> @@ -197,37 +212,25 @@ tid() </desc> </func> <func> - <name>file2tab(Filename) -> {ok,Tab} | {error,Reason}</name> + <name name="file2tab" arity="1"/> <fsummary>Read an ETS table from a file.</fsummary> - <type> - <v>Filename = string() | atom()</v> - <v>Tab = tid() | atom()</v> - <v>Reason = term()</v> - </type> <desc> <p>Reads a file produced by <seealso marker="#tab2file/2">tab2file/2</seealso> or <seealso marker="#tab2file/3">tab2file/3</seealso> and creates the - corresponding table <c>Tab</c>.</p> - <p>Equivalent to <c>file2tab(Filename,[])</c>.</p> + corresponding table <c><anno>Tab</anno></c>.</p> + <p>Equivalent to <c>file2tab(<anno>Filename</anno>, [])</c>.</p> </desc> </func> <func> - <name>file2tab(Filename,Options) -> {ok,Tab} | {error,Reason}</name> + <name name="file2tab" arity="2"/> <fsummary>Read an ETS table from a file.</fsummary> - <type> - <v>Filename = string() | atom()</v> - <v>Tab = tid() | atom()</v> - <v>Options = [Option]</v> - <v>Option = {verify, bool()}</v> - <v>Reason = term()</v> - </type> <desc> <p>Reads a file produced by <seealso marker="#tab2file/2">tab2file/2</seealso> or <seealso marker="#tab2file/3">tab2file/3</seealso> and creates the - corresponding table <c>Tab</c>.</p> - <p>The currently only supported option is <c>{verify,bool()}</c>. If + corresponding table <c><anno>Tab</anno></c>.</p> + <p>The currently only supported option is <c>{verify,boolean()}</c>. If verification is turned on (by means of specifying <c>{verify,true}</c>), the function utilizes whatever information is present in the file to assert that the @@ -271,70 +274,52 @@ tid() </desc> </func> <func> - <name>foldl(Function, Acc0, Tab) -> Acc1</name> + <name name="foldl" arity="3"/> <fsummary>Fold a function over an ETS table</fsummary> - <type> - <v>Function = fun(A, AccIn) -> AccOut</v> - <v>Tab = tid() | atom()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - </type> <desc> - <p><c>Acc0</c> is returned if the table is empty. + <p><c><anno>Acc0</anno></c> is returned if the table is empty. This function is similar to <c>lists:foldl/3</c>. The order in which the elements of the table are traversed is unspecified, except for tables of type <c>ordered_set</c>, for which they are traversed first to last.</p> - <p>If <c>Function</c> inserts objects into the table, or another + <p>If <c><anno>Function</anno></c> inserts objects into the table, or another process inserts objects into the table, those objects <em>may</em> (depending on key ordering) be included in the traversal.</p> </desc> </func> <func> - <name>foldr(Function, Acc0, Tab) -> Acc1</name> + <name name="foldr" arity="3"/> <fsummary>Fold a function over an ETS table</fsummary> - <type> - <v>Function = fun(A, AccIn) -> AccOut</v> - <v>Tab = tid() | atom()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - </type> <desc> - <p><c>Acc0</c> is returned if the table is empty. + <p><c><anno>Acc0</anno></c> is returned if the table is empty. This function is similar to <c>lists:foldr/3</c>. The order in which the elements of the table are traversed is unspecified, except for tables of type <c>ordered_set</c>, for which they are traversed last to first.</p> - <p>If <c>Function</c> inserts objects into the table, or another + <p>If <c><anno>Function</anno></c> inserts objects into the table, or another process inserts objects into the table, those objects <em>may</em> (depending on key ordering) be included in the traversal.</p> </desc> </func> <func> - <name>from_dets(Tab, DetsTab) -> true</name> + <name name="from_dets" arity="2"/> <fsummary>Fill an ETS table with objects from a Dets table.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>DetsTab = atom()</v> - </type> <desc> <p>Fills an already created ETS table with the objects in the - already opened Dets table named <c>DetsTab</c>. The existing + already opened Dets table named <c><anno>DetsTab</anno></c>. The existing objects of the ETS table are kept unless overwritten.</p> <p>Throws a badarg error if any of the tables does not exist or the dets table is not open.</p> </desc> </func> <func> - <name>fun2ms(LiteralFun) -> MatchSpec</name> + <name name="fun2ms" arity="1"/> <fsummary>Pseudo function that transforms fun syntax to a match_spec.</fsummary> - <type> - <v>LiteralFun -- see below</v> - <v>MatchSpec = match_spec()</v> - </type> <desc> <p>Pseudo function that by means of a <c>parse_transform</c> - translates <c>LiteralFun</c> typed as parameter in the + translates <c><anno>LiteralFun</anno></c> typed as parameter in the function call to a <seealso marker="#match_spec">match_spec</seealso>. With "literal" is meant that the fun needs to textually be written @@ -342,7 +327,7 @@ tid() variable which in turn is passed to the function).</p> <p>The parse transform is implemented in the module <c>ms_transform</c> and the source <em>must</em> include the - file <c>ms_transform.hrl</c> in <c>stdlib</c> for this + file <c>ms_transform.hrl</c> in STDLIB for this pseudo function to work. Failing to include the hrl file in the source will result in a runtime error, not a compile time ditto. The include file is easiest included by adding @@ -422,20 +407,17 @@ Error: fun containing local Erlang function calls </desc> </func> <func> - <name>i() -> ok</name> + <name name="i" arity="0"/> <fsummary>Display information about all ETS tables on tty.</fsummary> <desc> <p>Displays information about all ETS tables on tty.</p> </desc> </func> <func> - <name>i(Tab) -> ok</name> + <name name="i" arity="1"/> <fsummary>Browse an ETS table on tty.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - </type> <desc> - <p>Browses the table <c>Tab</c> on tty.</p> + <p>Browses the table <c><anno>Tab</anno></c> on tty.</p> </desc> </func> <func> @@ -454,7 +436,7 @@ Error: fun containing local Erlang function calls correct type, this function fails with reason <c>badarg</c>.</p> <list type="bulleted"> - <item><c>Item=memory, Value=int()</c> <br></br> + <item><c>Item=memory, Value=integer()</c> <br></br> The number of words allocated to the table.</item> <item><c>Item=owner, Value=pid()</c> <br></br> @@ -466,7 +448,7 @@ Error: fun containing local Erlang function calls <item><c>Item=name, Value=atom()</c> <br></br> The name of the table.</item> - <item><c>Item=size, Value=int()</c> <br></br> + <item><c>Item=size, Value=integer()</c> <br></br> The number of objects inserted in the table.</item> <item><c>Item=node, Value=atom()</c> <br></br> @@ -479,7 +461,7 @@ Error: fun containing local Erlang function calls <item><c>Item=type, Value=set|ordered_set|bag|duplicate_bag</c> <br></br> The table type.</item> - <item><c>Item=keypos, Value=int()</c> <br></br> + <item><c>Item=keypos, Value=integer()</c> <br></br> The key position.</item> <item><c>Item=protection, Value=public|protected|private</c> <br></br> @@ -530,31 +512,27 @@ Error: fun containing local Erlang function calls of the reference counter, keeping track of how many times the table has been fixed by the process.</p> <p>If the table never has been fixed, the call returns - <c>false</c>.</p> - </item> + <c>false</c>.</p></item> + <item><p><c>Item=stats, Value=tuple()</c> <br></br> + Returns internal statistics about set, bag and duplicate_bag tables on an internal format used by OTP test suites. + Not for production use.</p></item> </list> </desc> </func> <func> - <name>init_table(Name, InitFun) -> true</name> + <name name="init_table" arity="2"/> <fsummary>Replace all objects of an ETS table.</fsummary> - <type> - <v>Name = atom()</v> - <v>InitFun = fun(Arg) -> Res</v> - <v>Arg = read | close</v> - <v>Res = end_of_input | {[object()], InitFun} | term()</v> - </type> <desc> - <p>Replaces the existing objects of the table <c>Tab</c> with - objects created by calling the input function <c>InitFun</c>, + <p>Replaces the existing objects of the table <c><anno>Tab</anno></c> with + objects created by calling the input function <c><anno>InitFun</anno></c>, see below. This function is provided for compatibility with the <c>dets</c> module, it is not more efficient than filling a table by using <c>ets:insert/2</c>. </p> <p>When called with the argument <c>read</c> the function - <c>InitFun</c> is assumed to return <c>end_of_input</c> when - there is no more input, or <c>{Objects, Fun}</c>, where - <c>Objects</c> is a list of objects and <c>Fun</c> is a new + <c><anno>InitFun</anno></c> is assumed to return <c>end_of_input</c> when + there is no more input, or <c>{<anno>Objects</anno>, Fun}</c>, where + <c><anno>Objects</anno></c> is a list of objects and <c>Fun</c> is a new input function. Any other value Value is returned as an error <c>{error, {init_fun, Value}}</c>. Each input function will be called exactly once, and should an error occur, the last @@ -594,7 +572,7 @@ Error: fun containing local Erlang function calls </desc> </func> <func> - <name>insert_new(Tab, ObjectOrObjects) -> bool()</name> + <name>insert_new(Tab, ObjectOrObjects) -> boolean()</name> <fsummary>Insert an object into an ETS table if the key is not already present.</fsummary> <type> <v>Tab = tid() | atom()</v> @@ -615,7 +593,7 @@ Error: fun containing local Erlang function calls </desc> </func> <func> - <name>is_compiled_ms(Term) -> bool()</name> + <name>is_compiled_ms(Term) -> boolean()</name> <fsummary>Checks if an Erlang term is the result of ets:match_spec_compile</fsummary> <type> <v>Term = term()</v> @@ -682,9 +660,9 @@ ets:is_compiled_ms(Broken).</code> table. The difference being the same as between <c>=:=</c> and <c>==</c>. As an example, one might insert an object with the - <c>integer()</c><c>1</c> as a key in an <c>ordered_set</c> + <c>integer()</c> <c>1</c> as a key in an <c>ordered_set</c> and get the object returned as a result of doing a - <c>lookup/2</c> with the <c>float()</c><c>1.0</c> as the + <c>lookup/2</c> with the <c>float()</c> <c>1.0</c> as the key to search for.</p> <p>If the table is of type <c>set</c> or <c>ordered_set</c>, the function returns either the empty list or a list with one @@ -708,7 +686,7 @@ ets:is_compiled_ms(Broken).</code> <type> <v>Tab = tid() | atom()</v> <v>Key = term()</v> - <v>Pos = int()</v> + <v>Pos = integer()</v> <v>Elem = term() | [term()]</v> </type> <desc> @@ -802,15 +780,11 @@ ets:is_compiled_ms(Broken).</code> </desc> </func> <func> - <name>match_delete(Tab, Pattern) -> true</name> + <name name="match_delete" arity="2"/> <fsummary>Delete all objects which match a given pattern from an ETS table.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>Pattern = tuple()</v> - </type> <desc> - <p>Deletes all objects which match the pattern <c>Pattern</c> - from the table <c>Tab</c>. See <c>match/2</c> for a + <p>Deletes all objects which match the pattern <c><anno>Pattern</anno></c> + from the table <c><anno>Tab</anno></c>. See <c>match/2</c> for a description of patterns.</p> </desc> </func> @@ -957,8 +931,8 @@ ets:select(Table,MatchSpec),</code> <v> Option = Type | Access | named_table | {keypos,Pos} | {heir,pid(),HeirData} | {heir,none} | Tweaks</v> <v> Type = set | ordered_set | bag | duplicate_bag</v> <v> Access = public | protected | private</v> - <v> Tweaks = {write_concurrency,bool()} | {read_concurrency,bool()} | compressed</v> - <v> Pos = int()</v> + <v> Tweaks = {write_concurrency,boolean()} | {read_concurrency,boolean()} | compressed</v> + <v> Pos = integer()</v> <v> HeirData = term()</v> </type> <desc> @@ -971,7 +945,7 @@ ets:select(Table,MatchSpec),</code> table is named or not. If one or more options are left out, the default values are used. This means that not specifying any options (<c>[]</c>) is the same as specifying - <c>[set,protected,{keypos,1},{heir,none},{write_concurrency,false},{read_concurrency,false}]</c>.</p> + <c>[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}]</c>.</p> <list type="bulleted"> <item> <p><c>set</c> @@ -988,7 +962,7 @@ ets:select(Table,MatchSpec),</code> <c>ordered_set</c> tables regard keys as equal when they <em>compare equal</em>, not only when they match. This means that to an <c>ordered_set</c>, the - <c>integer()</c><c>1</c> and the <c>float()</c><c>1.0</c> are regarded as equal. This also means that the + <c>integer()</c> <c>1</c> and the <c>float()</c> <c>1.0</c> are regarded as equal. This also means that the key used to lookup an element not necessarily <em>matches</em> the key in the elements returned, if <c>float()</c>'s and <c>integer()</c>'s are mixed in @@ -1050,7 +1024,7 @@ ets:select(Table,MatchSpec),</code> </item> <item> <marker id="new_2_write_concurrency"></marker> - <p><c>{write_concurrency,bool()}</c> + <p><c>{write_concurrency,boolean()}</c> Performance tuning. Default is <c>false</c>, in which case an operation that mutates (writes to) the table will obtain exclusive access, blocking any concurrent access of the same table until finished. @@ -1074,7 +1048,7 @@ ets:select(Table,MatchSpec),</code> </item> <item> <marker id="new_2_read_concurrency"></marker> - <p><c>{read_concurrency,bool()}</c> + <p><c>{read_concurrency,boolean()}</c> Performance tuning. Default is <c>false</c>. When set to <c>true</c>, the table is optimized for concurrent read operations. When this option is enabled on a runtime system with @@ -1160,12 +1134,8 @@ ets:select(Table,MatchSpec),</code> </desc> </func> <func> - <name>repair_continuation(Continuation, MatchSpec) -> Continuation</name> + <name name="repair_continuation" arity="2"/> <fsummary>Repair a continuation from ets:select/1 or ets:select/3 that has passed through external representation</fsummary> - <type> - <v>Continuation = term()</v> - <v>MatchSpec = match_spec()</v> - </type> <desc> <p>This function can be used to restore an opaque continuation returned by <c>ets:select/3</c> or <c>ets:select/1</c> if the @@ -1551,7 +1521,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> <fsummary>Return all objects in a given slot of an ETS table.</fsummary> <type> <v>Tab = tid() | atom()</v> - <v>I = int()</v> + <v>I = integer()</v> <v>Object = tuple()</v> </type> <desc> @@ -1572,32 +1542,19 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> </desc> </func> <func> - <name>tab2file(Tab, Filename) -> ok | {error,Reason}</name> + <name name="tab2file" arity="2"/> <fsummary>Dump an ETS table to a file.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>Filename = string() | atom()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Dumps the table <c>Tab</c> to the file <c>Filename</c>.</p> - <p>Equivalent to <c>tab2file(Tab, Filename,[])</c></p> + <p>Dumps the table <c><anno>Tab</anno></c> to the file <c><anno>Filename</anno></c>.</p> + <p>Equivalent to <c>tab2file(<anno>Tab</anno>, <anno>Filename</anno>,[])</c></p> </desc> </func> <func> - <name>tab2file(Tab, Filename, Options) -> ok | {error,Reason}</name> + <name name="tab2file" arity="3"/> <fsummary>Dump an ETS table to a file.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>Filename = string() | atom()</v> - <v>Options = [Option]</v> - <v>Option = {extended_info, [ExtInfo]}</v> - <v>ExtInfo = object_count | md5sum</v> - <v>Reason = term()</v> - </type> <desc> - <p>Dumps the table <c>Tab</c> to the file <c>Filename</c>.</p> + <p>Dumps the table <c><anno>Tab</anno></c> to the file <c><anno>Filename</anno></c>.</p> <p>When dumping the table, certain information about the table is dumped to a header at the beginning of the dump. This information contains data about the table type, @@ -1634,26 +1591,15 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> </desc> </func> <func> - <name>tab2list(Tab) -> [Object]</name> + <name name="tab2list" arity="1"/> <fsummary>Return a list of all objects in an ETS table.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>Object = tuple()</v> - </type> <desc> - <p>Returns a list of all objects in the table <c>Tab</c>.</p> + <p>Returns a list of all objects in the table <c><anno>Tab</anno></c>.</p> </desc> </func> <func> - <name>tabfile_info(Filename) -> {ok, TableInfo} | {error, Reason}</name> + <name name="tabfile_info" arity="1"/> <fsummary>Return a list of all objects in an ETS table.</fsummary> - <type> - <v>Filename = string() | atom()</v> - <v>TableInfo = [InfoItem]</v> - <v>InfoItem = {InfoTag, term()}</v> - <v>InfoTag = name | type | protection | named_table | keypos | size | extended_info | version</v> - <v>Reason = term()</v> - </type> <desc> <p>Returns information about the table dumped to file by <seealso marker="#tab2file/2">tab2file/2</seealso> or @@ -1699,7 +1645,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> one or more of the atoms <c>object_count</c> and <c>md5sum</c>.</item> <tag>version</tag> - <item>A tuple <c>{Major,Minor}</c> containing the major and + <item>A tuple <c>{<anno>Major</anno>,<anno>Minor</anno>}</c> containing the major and minor version of the file format for ets table dumps. This version field was added beginning with stdlib-1.5.1, files dumped with older versions will return <c>{0,0}</c> in this @@ -1712,20 +1658,11 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code> </desc> </func> <func> - <name>table(Tab [, Options]) -> QueryHandle</name> + <name name="table" arity="1"/> + <name name="table" arity="2"/> <fsummary>Return a QLC query handle.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>QueryHandle = - a query handle, see qlc(3) -</v> - <v>Options = [Option] | Option</v> - <v>Option = {n_objects, NObjects} | {traverse, TraverseMethod}</v> - <v>NObjects = default | integer() > 0</v> - <v>TraverseMethod = first_next | last_prev | select | {select, MatchSpec}</v> - <v>MatchSpec = match_spec()</v> - </type> <desc> - <p> <marker id="qlc_table"></marker> -Returns a QLC (Query List + <p><marker id="qlc_table"></marker>Returns a QLC (Query List Comprehension) query handle. The module <c>qlc</c> implements a query language aimed mainly at Mnesia but ETS tables, Dets tables, and lists are also recognized by QLC as sources of @@ -1760,7 +1697,7 @@ Returns a QLC (Query List that matches all objects.</p> </item> <item> - <p><c>{select, MatchSpec}</c>. As for <c>select</c> + <p><c>{select, <anno>MatchSpec</anno>}</c>. As for <c>select</c> the table is traversed by calling <c>ets:select/3</c> and <c>ets:select/1</c>. The difference is that the match_spec is explicitly given. This is how to state @@ -1788,41 +1725,31 @@ true</pre> </desc> </func> <func> - <name>test_ms(Tuple, MatchSpec) -> {ok, Result} | {error, Errors}</name> + <name name="test_ms" arity="2"/> <fsummary>Test a match_spec for use in ets:select/2.</fsummary> - <type> - <v>Tuple = tuple()</v> - <v>MatchSpec = match_spec()</v> - <v>Result = term()</v> - <v>Errors = [{warning|error, string()}]</v> - </type> <desc> <p>This function is a utility to test a <seealso marker="#match_spec">match_spec</seealso> used in calls to <c>ets:select/2</c>. The function both tests - <c>MatchSpec</c> for "syntactic" correctness and runs the - match_spec against the object <c>Tuple</c>. If the match_spec - contains errors, the tuple <c>{error, Errors}</c> is returned - where <c>Errors</c> is a list of natural language + <c><anno>MatchSpec</anno></c> for "syntactic" correctness and runs the + match_spec against the object <c><anno>Tuple</anno></c>. If the match_spec + contains errors, the tuple <c>{error, <anno>Errors</anno>}</c> is returned + where <c><anno>Errors</anno></c> is a list of natural language descriptions of what was wrong with the match_spec. If the match_spec is syntactically OK, the function returns - <c>{ok,Term}</c> where <c>Term</c> is what would have been + <c>{ok,<anno>Result</anno>}</c> where <c><anno>Result</anno></c> is what would have been the result in a real <c>ets:select/2</c> call or <c>false</c> - if the match_spec does not match the object <c>Tuple</c>.</p> + if the match_spec does not match the object <c><anno>Tuple</anno></c>.</p> <p>This is a useful debugging and test tool, especially when writing complicated <c>ets:select/2</c> calls.</p> </desc> </func> <func> - <name>to_dets(Tab, DetsTab) -> DetsTab</name> + <name name="to_dets" arity="2"/> <fsummary>Fill a Dets table with objects from an ETS table.</fsummary> - <type> - <v>Tab = tid() | atom()</v> - <v>DetsTab = atom()</v> - </type> <desc> <p>Fills an already created/opened Dets table with the objects - in the already opened ETS table named <c>Tab</c>. The Dets + in the already opened ETS table named <c><anno>Tab</anno></c>. The Dets table is emptied before the objects are inserted.</p> </desc> </func> @@ -1835,7 +1762,7 @@ true</pre> <v>Tab = tid() | atom()</v> <v>Key = term()</v> <v>UpdateOp = {Pos,Incr} | {Pos,Incr,Threshold,SetValue}</v> - <v>Pos = Incr = Threshold = SetValue = Result = int()</v> + <v>Pos = Incr = Threshold = SetValue = Result = integer()</v> </type> <desc> <p>This function provides an efficient way to update one or more @@ -1897,7 +1824,7 @@ true</pre> <type> <v>Tab = tid() | atom()</v> <v>Key = Value = term()</v> - <v>Pos = int()</v> + <v>Pos = integer()</v> </type> <desc> <p>This function provides an efficient way to update one or more diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml index ccb32659a0..a6b3633066 100644 --- a/lib/stdlib/doc/src/file_sorter.xml +++ b/lib/stdlib/doc/src/file_sorter.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2010</year> + <year>2001</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -89,7 +89,7 @@ considerably. The <c>keysort</c>, <c>keymerge</c> and <c>keycheck</c> functions do not accept ordering functions. </item> - <item><c>{unique, bool()}</c>. When sorting or merging files, + <item><c>{unique, boolean()}</c>. When sorting or merging files, only the first of a sequence of terms that compare equal (<c>==</c>) is output if this option is set to <c>true</c>. The default value is <c>false</c> which implies that all terms that @@ -112,7 +112,7 @@ overwritten. Temporary files are deleted unless some uncaught EXIT signal occurs. </item> - <item><c>{compressed, bool()}</c>. Temporary files and the + <item><c>{compressed, boolean()}</c>. Temporary files and the output file may be compressed. The default value <c>false</c> implies that written files are not compressed. Regardless of the value of the <c>compressed</c> @@ -128,39 +128,6 @@ merged at a time. This option should rarely be needed. </item> </list> - <p>To summarize, here is the syntax of the options:</p> - <list type="bulleted"> - <item> - <p><c>Options = [Option] | Option</c></p> - </item> - <item> - <p><c>Option = {header, HeaderLength} | {format, Format} | {order, Order} | {unique, bool()} | {tmpdir, TempDirectory} | {compressed, bool()} | {size, Size} | {no_files, NoFiles}</c></p> - </item> - <item> - <p><c>HeaderLength = int() > 0</c></p> - </item> - <item> - <p><c>Format = binary_term | term | binary | FormatFun</c></p> - </item> - <item> - <p><c>FormatFun = fun(Binary) -> Term</c></p> - </item> - <item> - <p><c>Order = ascending | descending | OrderFun</c></p> - </item> - <item> - <p><c>OrderFun = fun(Term, Term) -> bool()</c></p> - </item> - <item> - <p><c>TempDirectory = "" | file_name()</c></p> - </item> - <item> - <p><c>Size = int() >= 0</c></p> - </item> - <item> - <p><c>NoFiles = int() > 1</c></p> - </item> - </list> <p>As an alternative to sorting files, a function of one argument can be given as input. When called with the argument <c>read</c> the function is assumed to return <c>end_of_input</c> or @@ -234,8 +201,8 @@ output(L) -> occurs are:</p> <list type="bulleted"> <item> - <p><c>bad_object</c>, <c>{bad_object, FileName}</c>. - Applying the format function failed for some binary, + <p><c>bad_object</c>, <c>{bad_object, FileName}</c>. + Applying the format function failed for some binary, or the key(s) could not be extracted from some term.</p> </item> <item> @@ -243,148 +210,181 @@ output(L) -> to read some term.</p> </item> <item> - <p><c>{file_error, FileName, Reason2}</c>. See - <c>file(3)</c> for an explanation of <c>Reason2</c>.</p> + <p><c>{file_error, FileName, file:posix()}</c>. See + <c>file(3)</c> for an explanation of <c>file:posix()</c>.</p> </item> <item> - <p><c>{premature_eof, FileName}</c>. End-of-file was + <p><c>{premature_eof, FileName}</c>. End-of-file was encountered inside some binary term.</p> </item> </list> - <p><em>Types</em></p> - <pre> -Binary = binary() -FileName = file_name() -FileNames = [FileName] -ICommand = read | close -IReply = end_of_input | {end_of_input, Value} | {[Object], Infun} | InputReply -Infun = fun(ICommand) -> IReply -Input = FileNames | Infun -InputReply = Term -KeyPos = int() > 0 | [int() > 0] -OCommand = {value, Value} | [Object] | close -OReply = Outfun | OutputReply -Object = Term | Binary -Outfun = fun(OCommand) -> OReply -Output = FileName | Outfun -OutputReply = Term -Term = term() -Value = Term</pre> </description> + + <datatypes> + <datatype> + <name name="file_name"/><br/> + </datatype> + <datatype> + <name name="file_names"/><br/> + </datatype> + <datatype> + <name name="i_command"/><br/> + </datatype> + <datatype> + <name name="i_reply"/><br/> + </datatype> + <datatype> + <name name="infun"/><br/> + </datatype> + <datatype> + <name name="input"/><br/> + </datatype> + <datatype> + <name name="input_reply"/><br/> + </datatype> + <datatype> + <name name="o_command"/><br/> + </datatype> + <datatype> + <name name="o_reply"/><br/> + </datatype> + <datatype> + <name name="object"/><br/> + </datatype> + <datatype> + <name name="outfun"/><br/> + </datatype> + <datatype> + <name name="output"/><br/> + </datatype> + <datatype> + <name name="output_reply"/><br/> + </datatype> + <datatype> + <name name="value"/><br/> + </datatype> + <datatype> + <name name="options"/><br/> + </datatype> + <datatype> + <name name="option"/><br/> + </datatype> + <datatype> + <name name="format"/><br/> + </datatype> + <datatype> + <name name="format_fun"/><br/> + </datatype> + <datatype> + <name name="header_length"/><br/> + </datatype> + <datatype> + <name name="key_pos"/><br/> + </datatype> + <datatype> + <name name="no_files"/><br/> + </datatype> + <datatype> + <name name="order"/><br/> + </datatype> + <datatype> + <name name="order_fun"/><br/> + </datatype> + <datatype> + <name name="size"/><br/> + </datatype> + <datatype> + <name name="tmp_directory"/><br/> + </datatype> + <datatype> + <name name="reason"/><br/> + </datatype> + </datatypes> + <funcs> <func> - <name>sort(FileName) -> Reply</name> - <name>sort(Input, Output) -> Reply</name> - <name>sort(Input, Output, Options) -> Reply</name> + <name name="sort" arity="1"/> <fsummary>Sort terms on files.</fsummary> - <type> - <v>Reply = ok | {error, Reason} | InputReply | OutputReply</v> - </type> <desc> - <p>Sorts terms on files. - </p> - <p><c>sort(FileName)</c> is equivalent to - <c>sort([FileName], FileName)</c>. - </p> - <p><c>sort(Input, Output)</c> is equivalent to - <c>sort(Input, Output, [])</c>. - </p> - <p></p> + <p>Sorts terms on files. <c>sort(FileName)</c> is equivalent + to <c>sort([FileName], FileName)</c>.</p> + </desc> + </func> + <func> + <name name="sort" arity="2"/> + <name name="sort" arity="3"/> + <fsummary>Sort terms on files.</fsummary> + <desc> + <p>Sorts terms on files. <c>sort(Input, Output)</c> is + equivalent to <c>sort(Input, Output, [])</c>.</p> + </desc> + </func> + <func> + <name name="keysort" arity="2"/> + <fsummary>Sort terms on files by key.</fsummary> + <desc> + <p>Sorts tuples on files. <c>keysort(N, FileName)</c> is + equivalent to <c>keysort(N, [FileName], FileName)</c>.</p> </desc> </func> <func> - <name>keysort(KeyPos, FileName) -> Reply</name> - <name>keysort(KeyPos, Input, Output) -> Reply</name> - <name>keysort(KeyPos, Input, Output, Options) -> Reply</name> + <name name="keysort" arity="3"/> + <name name="keysort" arity="4"/> <fsummary>Sort terms on files by key.</fsummary> - <type> - <v>Reply = ok | {error, Reason} | InputReply | OutputReply</v> - </type> <desc> <p>Sorts tuples on files. The sort is performed on the - element(s) mentioned in <c>KeyPos</c>. If two tuples - compare equal (<c>==</c>) on one element, next element according to - <c>KeyPos</c> is compared. The sort is stable. - </p> - <p><c>keysort(N, FileName)</c> is equivalent to - <c>keysort(N, [FileName], FileName)</c>. - </p> + element(s) mentioned in <c><anno>KeyPos</anno></c>. If two + tuples compare equal (<c>==</c>) on one element, next + element according to <c><anno>KeyPos</anno></c> + is compared. The sort is stable.</p> <p><c>keysort(N, Input, Output)</c> is equivalent to - <c>keysort(N, Input, Output, [])</c>. - </p> - <p></p> + <c>keysort(N, Input, Output, [])</c>.</p> </desc> </func> <func> - <name>merge(FileNames, Output) -> Reply</name> - <name>merge(FileNames, Output, Options) -> Reply</name> + <name name="merge" arity="2"/> + <name name="merge" arity="3"/> <fsummary>Merge terms on files.</fsummary> - <type> - <v>Reply = ok | {error, Reason} | OutputReply</v> - </type> <desc> <p>Merges terms on files. Each input file is assumed to be - sorted. - </p> + sorted.</p> <p><c>merge(FileNames, Output)</c> is equivalent to - <c>merge(FileNames, Output, [])</c>. - </p> + <c>merge(FileNames, Output, [])</c>.</p> </desc> </func> <func> - <name>keymerge(KeyPos, FileNames, Output) -> Reply</name> - <name>keymerge(KeyPos, FileNames, Output, Options) -> Reply</name> + <name name="keymerge" arity="3"/> + <name name="keymerge" arity="4"/> <fsummary>Merge terms on files by key.</fsummary> - <type> - <v>Reply = ok | {error, Reason} | OutputReply</v> - </type> <desc> <p>Merges tuples on files. Each input file is assumed to be - sorted on key(s). - </p> + sorted on key(s).</p> <p><c>keymerge(KeyPos, FileNames, Output)</c> is equivalent - to <c>keymerge(KeyPos, FileNames, Output, [])</c>. - </p> - <p></p> + to <c>keymerge(KeyPos, FileNames, Output, [])</c>.</p> </desc> </func> <func> - <name>check(FileName) -> Reply</name> - <name>check(FileNames, Options) -> Reply</name> + <name name="check" arity="1"/> + <name name="check" arity="2"/> <fsummary>Check whether terms on files are sorted.</fsummary> - <type> - <v>Reply = {ok, [Result]} | {error, Reason}</v> - <v>Result = {FileName, TermPosition, Term}</v> - <v>TermPosition = int() > 1</v> - </type> <desc> <p>Checks files for sortedness. If a file is not sorted, the first out-of-order element is returned. The first term on a - file has position 1. - </p> + file has position 1.</p> <p><c>check(FileName)</c> is equivalent to - <c>check([FileName], [])</c>. - </p> + <c>check([FileName], [])</c>.</p> </desc> </func> <func> - <name>keycheck(KeyPos, FileName) -> CheckReply</name> - <name>keycheck(KeyPos, FileNames, Options) -> Reply</name> + <name name="keycheck" arity="2"/> + <name name="keycheck" arity="3"/> <fsummary>Check whether terms on files are sorted by key.</fsummary> - <type> - <v>Reply = {ok, [Result]} | {error, Reason}</v> - <v>Result = {FileName, TermPosition, Term}</v> - <v>TermPosition = int() > 1</v> - </type> <desc> <p>Checks files for sortedness. If a file is not sorted, the first out-of-order element is returned. The first term on a - file has position 1. - </p> + file has position 1.</p> <p><c>keycheck(KeyPos, FileName)</c> is equivalent - to <c>keycheck(KeyPos, [FileName], [])</c>. - </p> - <p></p> + to <c>keycheck(KeyPos, [FileName], [])</c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml index fab68ae77c..f3079c7337 100644 --- a/lib/stdlib/doc/src/filelib.xml +++ b/lib/stdlib/doc/src/filelib.xml @@ -41,62 +41,46 @@ <p>For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -filename() = string() | atom() | DeepList | RawFilename - DeepList = [char() | atom() | DeepList] - RawFilename = binary() - If VM is in unicode filename mode, string() and char() are allowed to be > 255. - RawFilename is a filename not subject to Unicode translation, meaning that it - can contain characters not conforming to the Unicode encoding expected from the - filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode - filename mode). -dirname() = filename()</code> - </section> + <datatypes> + <datatype> + <name name="filename"/> + </datatype> + <datatype> + <name name="dirname"/> + </datatype> + </datatypes> <funcs> <func> - <name>ensure_dir(Name) -> ok | {error, Reason}</name> + <name name="ensure_dir" arity="1"/> <fsummary>Ensure that all parent directories for a file or directory exist.</fsummary> - <type> - <v>Name = filename() | dirname()</v> - <v>Reason = posix() -- see file(3)</v> - </type> <desc> <p>The <c>ensure_dir/1</c> function ensures that all parent - directories for the given file or directory name <c>Name</c> + directories for the given file or directory name <c><anno>Name</anno></c> exist, trying to create them if necessary.</p> <p>Returns <c>ok</c> if all parent directories already exist - or could be created, or <c>{error, Reason}</c> if some parent + or could be created, or <c>{error, <anno>Reason</anno>}</c> if some parent directory does not exist and could not be created for some reason.</p> </desc> </func> <func> - <name>file_size(Filename) -> integer()</name> + <name name="file_size" arity="1"/> <fsummary>Return the size in bytes of the file.</fsummary> <desc> <p>The <c>file_size</c> function returns the size of the given file.</p> </desc> </func> <func> - <name>fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut </name> + <name name="fold_files" arity="5"/> <fsummary>Fold over all files matching a regular expression.</fsummary> - <type> - <v>Dir = dirname()</v> - <v>RegExp = regular_expression_string()</v> - <v>Recursive = true|false</v> - <v>Fun = fun(F, AccIn) -> AccOut</v> - <v>AccIn = AccOut = term()</v> - </type> <desc> <p>The <c>fold_files/5</c> function folds the function - <c>Fun</c> over all (regular) files <c>F</c> in the - directory <c>Dir</c> that match the regular expression <c>RegExp</c> + <c><anno>Fun</anno></c> over all (regular) files <c><anno>F</anno></c> in the + directory <c><anno>Dir</anno></c> that match the regular expression <c><anno>RegExp</anno></c> (see the <seealso marker="re">re</seealso> module for a description of the allowed regular expressions). - If <c>Recursive</c> is true all sub-directories to <c>Dir</c> + If <c><anno>Recursive</anno></c> is true all sub-directories to <c>Dir</c> are processed. The regular expression matching is done on just the filename without the directory part.</p> @@ -114,44 +98,32 @@ dirname() = filename()</code> </desc> </func> <func> - <name>is_dir(Name) -> true | false</name> + <name name="is_dir" arity="1"/> <fsummary>Test whether Name refer to a directory or not</fsummary> - <type> - <v>Name = filename() | dirname()</v> - </type> <desc> - <p>The <c>is_dir/1</c> function returns <c>true</c> if <c>Name</c> + <p>The <c>is_dir/1</c> function returns <c>true</c> if <c><anno>Name</anno></c> refers to a directory, and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_file(Name) -> true | false</name> + <name name="is_file" arity="1"/> <fsummary>Test whether Name refer to a file or directory.</fsummary> - <type> - <v>Name = filename() | dirname()</v> - </type> <desc> - <p>The <c>is_file/1</c> function returns <c>true</c> if <c>Name</c> + <p>The <c>is_file/1</c> function returns <c>true</c> if <c><anno>Name</anno></c> refers to a file or a directory, and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_regular(Name) -> true | false</name> + <name name="is_regular" arity="1"/> <fsummary>Test whether Name refer to a (regular) file.</fsummary> - <type> - <v>Name = filename()</v> - </type> <desc> - <p>The <c>is_regular/1</c> function returns <c>true</c> if <c>Name</c> + <p>The <c>is_regular/1</c> function returns <c>true</c> if <c><anno>Name</anno></c> refers to a file (regular file), and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>last_modified(Name) -> {{Year,Month,Day},{Hour,Min,Sec}} | 0</name> + <name name="last_modified" arity="1"/> <fsummary>Return the local date and time when a file was last modified.</fsummary> - <type> - <v>Name = filename() | dirname()</v> - </type> <desc> <p>The <c>last_modified/1</c> function returns the date and time the given file or directory was last modified, or 0 if the file @@ -159,14 +131,11 @@ dirname() = filename()</code> </desc> </func> <func> - <name>wildcard(Wildcard) -> list()</name> + <name name="wildcard" arity="1"/> <fsummary>Match filenames using Unix-style wildcards.</fsummary> - <type> - <v>Wildcard = filename() | dirname()</v> - </type> <desc> <p>The <c>wildcard/1</c> function returns a list of all files - that match Unix-style wildcard-string <c>Wildcard</c>.</p> + that match Unix-style wildcard-string <c><anno>Wildcard</anno></c>.</p> <p>The wildcard string looks like an ordinary filename, except that certain "wildcard characters" are interpreted in a special way. The following characters are special: @@ -226,15 +195,11 @@ dirname() = filename()</code> </desc> </func> <func> - <name>wildcard(Wildcard, Cwd) -> list()</name> + <name name="wildcard" arity="2"/> <fsummary>Match filenames using Unix-style wildcards starting at a specified directory.</fsummary> - <type> - <v>Wildcard = filename() | dirname()</v> - <v>Cwd = dirname()</v> - </type> <desc> <p>The <c>wildcard/2</c> function works like <c>wildcard/1</c>, - except that instead of the actual working directory, <c>Cwd</c> + except that instead of the actual working directory, <c><anno>Cwd</anno></c> will be used.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml index cdee6e4a81..bc3a616d39 100644 --- a/lib/stdlib/doc/src/filename.xml +++ b/lib/stdlib/doc/src/filename.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2010</year> + <year>1997</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -47,28 +47,12 @@ <seealso marker="kernel:file#native_name_encoding/0">file:native_name_encoding/0</seealso>, a raw file name will also be returned. For example filename:join/1 provided with a path component being a binary (and also not being possible to interpret under the current native file name encoding) will result in a raw file name being returned (the join operation will have been performed of course). For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -name() = string() | atom() | DeepList | RawFilename - DeepList = [char() | atom() | DeepList] - RawFilename = binary() - If VM is in unicode filename mode, string() and char() are allowed to be > 255. - RawFilename is a filename not subject to Unicode translation, meaning that it - can contain characters not conforming to the Unicode encoding expected from the - filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode - filename mode). - </code> - </section> <funcs> <func> - <name>absname(Filename) -> string()</name> + <name name="absname" arity="1"/> <fsummary>Convert a filename to an absolute name, relative the working directory</fsummary> - <type> - <v>Filename = name()</v> - </type> <desc> - <p>Converts a relative <c>Filename</c> and returns an absolute + <p>Converts a relative <c><anno>Filename</anno></c> and returns an absolute name. No attempt is made to create the shortest absolute name, because this can give incorrect results on file systems which allow links.</p> @@ -95,44 +79,33 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>absname(Filename, Dir) -> string()</name> + <name name="absname" arity="2"/> <fsummary>Convert a filename to an absolute name, relative a specified directory</fsummary> - <type> - <v>Filename = name()</v> - <v>Dir = string()</v> - </type> <desc> <p>This function works like <c>absname/1</c>, except that the directory to which the file name should be made relative - is given explicitly in the <c>Dir</c> argument.</p> + is given explicitly in the <c><anno>Dir</anno></c> argument.</p> </desc> </func> <func> - <name>absname_join(Dir, Filename) -> string()</name> + <name name="absname_join" arity="2"/> <fsummary>Join an absolute directory with a relative filename</fsummary> - <type> - <v>Dir = string()</v> - <v>Filename = name()</v> - </type> <desc> <p>Joins an absolute directory with a relative filename. Similar to <c>join/2</c>, but on platforms with tight restrictions on raw filename length and no support for symbolic links (read: VxWorks), leading parent directory - components in <c>Filename</c> are matched against trailing - directory components in <c>Dir</c> so they can be removed + components in <c><anno>Filename</anno></c> are matched against trailing + directory components in <c><anno>Dir</anno></c> so they can be removed from the result - minimizing its length.</p> </desc> </func> <func> - <name>basename(Filename) -> string()</name> + <name name="basename" arity="1"/> <fsummary>Return the last component of a filename</fsummary> - <type> - <v>Filename = name()</v> - </type> <desc> - <p>Returns the last component of <c>Filename</c>, or - <c>Filename</c> itself if it does not contain any directory + <p>Returns the last component of <c><anno>Filename</anno></c>, or + <c><anno>Filename</anno></c> itself if it does not contain any directory separators.</p> <pre> 5> <input>filename:basename("foo").</input> @@ -144,14 +117,11 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>basename(Filename, Ext) -> string()</name> + <name name="basename" arity="2"/> <fsummary>Return the last component of a filename, stripped of the specified extension</fsummary> - <type> - <v>Filename = Ext = name()</v> - </type> <desc> - <p>Returns the last component of <c>Filename</c> with the - extension <c>Ext</c> stripped. This function should be used + <p>Returns the last component of <c><anno>Filename</anno></c> with the + extension <c><anno>Ext</anno></c> stripped. This function should be used to remove a specific extension which might, or might not, be there. Use <c>rootname(basename(Filename))</c> to remove an extension that exists, but you are not sure which one it is.</p> @@ -169,13 +139,10 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>dirname(Filename) -> string()</name> + <name name="dirname" arity="1"/> <fsummary>Return the directory part of a path name</fsummary> - <type> - <v>Filename = name()</v> - </type> <desc> - <p>Returns the directory part of <c>Filename</c>.</p> + <p>Returns the directory part of <c><anno>Filename</anno></c>.</p> <pre> 13> <input>filename:dirname("/usr/src/kalle.erl").</input> "/usr/src" @@ -187,13 +154,10 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>extension(Filename) -> string()</name> + <name name="extension" arity="1"/> <fsummary>Return the file extension</fsummary> - <type> - <v>Filename = name()</v> - </type> <desc> - <p>Returns the file extension of <c>Filename</c>, including + <p>Returns the file extension of <c><anno>Filename</anno></c>, including the period. Returns an empty string if there is no extension.</p> <pre> 15> <input>filename:extension("foo.erl").</input> @@ -203,11 +167,8 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>flatten(Filename) -> string()</name> + <name name="flatten" arity="1"/> <fsummary>Convert a filename to a flat string</fsummary> - <type> - <v>Filename = name()</v> - </type> <desc> <p>Converts a possibly deep list filename consisting of characters and atoms into the corresponding flat string @@ -215,14 +176,11 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>join(Components) -> string()</name> + <name name="join" arity="1"/> <fsummary>Join a list of filename components with directory separators</fsummary> - <type> - <v>Components = [string()]</v> - </type> <desc> - <p>Joins a list of file name <c>Components</c> with directory - separators. If one of the elements of <c>Components</c> + <p>Joins a list of file name <c><anno>Components</anno></c> with directory + separators. If one of the elements of <c><anno>Components</anno></c> includes an absolute path, for example <c>"/xxx"</c>, the preceding elements, if any, are removed from the result.</p> <p>The result is "normalized":</p> @@ -242,24 +200,18 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>join(Name1, Name2) -> string()</name> + <name name="join" arity="2"/> <fsummary>Join two filename components with directory separators</fsummary> - <type> - <v>Name1 = Name2 = string()</v> - </type> <desc> <p>Joins two file name components with directory separators. - Equivalent to <c>join([Name1, Name2])</c>.</p> + Equivalent to <c>join([<anno>Name1</anno>, <anno>Name2</anno>])</c>.</p> </desc> </func> <func> - <name>nativename(Path) -> string()</name> + <name name="nativename" arity="1"/> <fsummary>Return the native form of a file path</fsummary> - <type> - <v>Path = string()</v> - </type> <desc> - <p>Converts <c>Path</c> to a form accepted by the command shell + <p>Converts <c><anno>Path</anno></c> to a form accepted by the command shell and native applications on the current platform. On Windows, forward slashes is converted to backward slashes. On all platforms, the name is normalized as done by <c>join/1</c>.</p> @@ -272,7 +224,7 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>pathtype(Path) -> absolute | relative | volumerelative</name> + <name name="pathtype" arity="1"/> <fsummary>Return the type of a path</fsummary> <desc> <p>Returns the type of path, one of <c>absolute</c>, @@ -302,16 +254,13 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>rootname(Filename) -> string()</name> - <name>rootname(Filename, Ext) -> string()</name> + <name name="rootname" arity="1"/> + <name name="rootname" arity="2"/> <fsummary>Remove a filename extension</fsummary> - <type> - <v>Filename = Ext = name()</v> - </type> <desc> <p>Remove a filename extension. <c>rootname/2</c> works as <c>rootname/1</c>, except that the extension is removed only - if it is <c>Ext</c>.</p> + if it is <c><anno>Ext</anno></c>.</p> <pre> 20> <input>filename:rootname("/beam.src/kalle").</input> /beam.src/kalle" @@ -324,15 +273,11 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>split(Filename) -> Components</name> + <name name="split" arity="1"/> <fsummary>Split a filename into its path components</fsummary> - <type> - <v>Filename = name()</v> - <v>Components = [string()]</v> - </type> <desc> <p>Returns a list whose elements are the path components of - <c>Filename</c>.</p> + <c><anno>Filename</anno></c>.</p> <pre> 24> <input>filename:split("/usr/local/bin").</input> ["/","usr","local","bin"] @@ -343,47 +288,38 @@ name() = string() | atom() | DeepList | RawFilename </desc> </func> <func> - <name>find_src(Beam) -> {SourceFile, Options} | {error,{ErrorReason,Module}}</name> - <name>find_src(Beam, Rules) -> {SourceFile, Options} | {error,{ErrorReason,Module}}</name> + <name name="find_src" arity="1"/> + <name name="find_src" arity="2"/> <fsummary>Find the filename and compiler options for a module</fsummary> - <type> - <v>Beam = Module | Filename</v> - <v> Module = atom()</v> - <v> Filename = string() | atom()</v> - <v>SourceFile = string()</v> - <v>Options = [Opt]</v> - <v> Opt = {i, string()} | {outdir, string()} | {d, atom()}</v> - <v>ErrorReason = non_existing | preloaded | interpreted</v> - </type> <desc> <p>Finds the source filename and compiler options for a module. The result can be fed to <c>compile:file/2</c> in order to compile the file again.</p> - <p>The <c>Beam</c> argument, which can be a string or an atom, + <p>The <c><anno>Beam</anno></c> argument, which can be a string or an atom, specifies either the module name or the path to the source code, with or without the <c>".erl"</c> extension. In either case, the module must be known by the code server, i.e. - <c>code:which(Module)</c> must succeed.</p> - <p><c>Rules</c> describes how the source directory can be found, + <c>code:which(<anno>Module</anno>)</c> must succeed.</p> + <p><c><anno>Rules</anno></c> describes how the source directory can be found, when the object code directory is known. It is a list of - tuples <c>{BinSuffix, SourceSuffix}</c> and is interpreted + tuples <c>{<anno>BinSuffix</anno>, <anno>SourceSuffix</anno>}</c> and is interpreted as follows: If the end of the directory name where the object - is located matches <c>BinSuffix</c>, then the source code - directory has the same name, but with <c>BinSuffix</c> - replaced by <c>SourceSuffix</c>. <c>Rules</c> defaults to:</p> + is located matches <c><anno>BinSuffix</anno></c>, then the source code + directory has the same name, but with <c><anno>BinSuffix</anno></c> + replaced by <c><anno>SourceSuffix</anno></c>. <c><anno>Rules</anno></c> defaults to:</p> <code type="none"> [{"", ""}, {"ebin", "src"}, {"ebin", "esrc"}]</code> <p>If the source file is found in the resulting directory, then the function returns that location together with - <c>Options</c>. Otherwise, the next rule is tried, and so on.</p> + <c><anno>Options</anno></c>. Otherwise, the next rule is tried, and so on.</p> - <p>The function returns <c>{SourceFile, Options}</c> if it succeeds. - <c>SourceFile</c> is the absolute path to the source file - without the <c>".erl"</c> extension. <c>Options</c> include + <p>The function returns <c>{<anno>SourceFile</anno>, <anno>Options</anno>}</c> if it succeeds. + <c><anno>SourceFile</anno></c> is the absolute path to the source file + without the <c>".erl"</c> extension. <c><anno>Options</anno></c> include the options which are necessary to recompile the file with <c>compile:file/2</c>, but excludes options such as <c>report</c> or <c>verbose</c> which do not change the way - code is generated. The paths in the <c>{outdir, Path}</c> + code is generated. The paths in the <c>{outdir, <anno>Path</anno>}</c> and <c>{i, Path}</c> options are guaranteed to be absolute.</p> diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml index 60d8bcbfa3..f91fac9c82 100644 --- a/lib/stdlib/doc/src/gb_sets.xml +++ b/lib/stdlib/doc/src/gb_sets.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2010</year> + <year>2001</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -61,7 +61,6 @@ and do the same thing in the <c>sets</c> and <c>ordsets</c> modules. That is, by only changing the module name for each call, you can try out different set representations.</p> - <p></p> <list type="bulleted"> <item> <p><c>add_element/2</c></p> @@ -114,34 +113,32 @@ </list> </section> - <section> - <title>DATA TYPES</title> - <code type="none"> -gb_set() = a GB set</code> - </section> + <datatypes> + <datatype> + <name><marker id="type-gb_set">gb_set()</marker></name> + <desc><p>A GB set.</p></desc> + </datatype> + <datatype> + <name name="iter"/> + <desc><p>A GB set iterator.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>add(Element, Set1) -> Set2</name> - <name>add_element(Element, Set1) -> Set2</name> + <name name="add" arity="2"/> + <name name="add_element" arity="2"/> <fsummary>Add a (possibly existing) element to a gb_set</fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns a new gb_set formed from <c>Set1</c> with - <c>Element</c> inserted. If <c>Element</c> is already an - element in <c>Set1</c>, nothing is changed.</p> + <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with + <c><anno>Element</anno></c> inserted. If <c><anno>Element</anno></c> is already an + element in <c><anno>Set1</anno></c>, nothing is changed.</p> </desc> </func> <func> - <name>balance(Set1) -> Set2</name> + <name name="balance" arity="1"/> <fsummary>Rebalance tree representation of a gb_set</fsummary> - <type> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Rebalances the tree representation of <c>Set1</c>. Note that + <p>Rebalances the tree representation of <c><anno>Set1</anno></c>. Note that this is rarely necessary, but may be motivated when a large number of elements have been deleted from the tree without further insertions. Rebalancing could then be forced in order @@ -150,208 +147,144 @@ gb_set() = a GB set</code> </desc> </func> <func> - <name>delete(Element, Set1) -> Set2</name> + <name name="delete" arity="2"/> <fsummary>Remove an element from a gb_set</fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns a new gb_set formed from <c>Set1</c> with - <c>Element</c> removed. Assumes that <c>Element</c> is present - in <c>Set1</c>.</p> + <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with + <c><anno>Element</anno></c> removed. Assumes that <c><anno>Element</anno></c> is present + in <c><anno>Set1</anno></c>.</p> </desc> </func> <func> - <name>delete_any(Element, Set1) -> Set2</name> - <name>del_element(Element, Set1) -> Set2</name> + <name name="delete_any" arity="2"/> + <name name="del_element" arity="2"/> <fsummary>Remove a (possibly non-existing) element from a gb_set</fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns a new gb_set formed from <c>Set1</c> with - <c>Element</c> removed. If <c>Element</c> is not an element - in <c>Set1</c>, nothing is changed.</p> + <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with + <c><anno>Element</anno></c> removed. If <c><anno>Element</anno></c> is not an element + in <c><anno>Set1</anno></c>, nothing is changed.</p> </desc> </func> <func> - <name>difference(Set1, Set2) -> Set3</name> - <name>subtract(Set1, Set2) -> Set3</name> + <name name="difference" arity="2"/> + <name name="subtract" arity="2"/> <fsummary>Return the difference of two gb_sets</fsummary> - <type> - <v>Set1 = Set2 = Set3 = gb_set()</v> - </type> <desc> - <p>Returns only the elements of <c>Set1</c> which are not also - elements of <c>Set2</c>.</p> + <p>Returns only the elements of <c><anno>Set1</anno></c> which are not also + elements of <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>empty() -> Set</name> - <name>new() -> Set</name> + <name name="empty" arity="0"/> + <name name="new" arity="0"/> <fsummary>Return an empty gb_set</fsummary> - <type> - <v>Set = gb_set()</v> - </type> <desc> <p>Returns a new empty gb_set.</p> </desc> </func> <func> - <name>filter(Pred, Set1) -> Set2</name> + <name name="filter" arity="2"/> <fsummary>Filter gb_set elements</fsummary> - <type> - <v>Pred = fun (E) -> bool()</v> - <v> E = term()</v> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Filters elements in <c>Set1</c> using predicate function - <c>Pred</c>.</p> + <p>Filters elements in <c><anno>Set1</anno></c> using predicate function + <c><anno>Pred</anno></c>.</p> </desc> </func> <func> - <name>fold(Function, Acc0, Set) -> Acc1</name> + <name name="fold" arity="3"/> <fsummary>Fold over gb_set elements</fsummary> - <type> - <v>Function = fun (E, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v> E = term()</v> - <v>Set = gb_set()</v> - </type> <desc> - <p>Folds <c>Function</c> over every element in <c>Set</c> + <p>Folds <c><anno>Function</anno></c> over every element in <c><anno>Set</anno></c> returning the final value of the accumulator.</p> </desc> </func> <func> - <name>from_list(List) -> Set</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list into a gb_set</fsummary> - <type> - <v>List = [term()]</v> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns a gb_set of the elements in <c>List</c>, where - <c>List</c> may be unordered and contain duplicates.</p> + <p>Returns a gb_set of the elements in <c><anno>List</anno></c>, where + <c><anno>List</anno></c> may be unordered and contain duplicates.</p> </desc> </func> <func> - <name>from_ordset(List) -> Set</name> + <name name="from_ordset" arity="1"/> <fsummary>Make a gb_set from an ordset list</fsummary> - <type> - <v>List = [term()]</v> - <v>Set = gb_set()</v> - </type> <desc> - <p>Turns an ordered-set list <c>List</c> into a gb_set. The list + <p>Turns an ordered-set list <c><anno>List</anno></c> into a gb_set. The list must not contain duplicates.</p> </desc> </func> <func> - <name>insert(Element, Set1) -> Set2</name> + <name name="insert" arity="2"/> <fsummary>Add a new element to a gb_set</fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns a new gb_set formed from <c>Set1</c> with - <c>Element</c> inserted. Assumes that <c>Element</c> is not - present in <c>Set1</c>.</p> + <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with + <c><anno>Element</anno></c> inserted. Assumes that <c><anno>Element</anno></c> is not + present in <c><anno>Set1</anno></c>.</p> </desc> </func> <func> - <name>intersection(Set1, Set2) -> Set3</name> + <name name="intersection" arity="2"/> <fsummary>Return the intersection of two gb_sets</fsummary> - <type> - <v>Set1 = Set2 = Set3 = gb_set()</v> - </type> <desc> - <p>Returns the intersection of <c>Set1</c> and <c>Set2</c>.</p> + <p>Returns the intersection of <c><anno>Set1</anno></c> and <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>intersection(SetList) -> Set</name> + <name name="intersection" arity="1"/> <fsummary>Return the intersection of a list of gb_sets</fsummary> - <type> - <v>SetList = [gb_set()]</v> - <v>Set = gb_set()</v> - </type> <desc> <p>Returns the intersection of the non-empty list of gb_sets.</p> </desc> </func> <func> - <name>is_disjoint(Set1, Set2) -> bool()</name> + <name name="is_disjoint" arity="2"/> <fsummary>Check whether two gb_sets are disjoint</fsummary> - <type> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Set1</c> and - <c>Set2</c> are disjoint (have no elements in common), + <p>Returns <c>true</c> if <c><anno>Set1</anno></c> and + <c><anno>Set2</anno></c> are disjoint (have no elements in common), and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_empty(Set) -> bool()</name> + <name name="is_empty" arity="1"/> <fsummary>Test for empty gb_set</fsummary> - <type> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Set</c> is an empty set, and + <p>Returns <c>true</c> if <c><anno>Set</anno></c> is an empty set, and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_member(Element, Set) -> bool()</name> - <name>is_element(Element, Set) -> bool()</name> + <name name="is_member" arity="2"/> + <name name="is_element" arity="2"/> <fsummary>Test for membership of a gb_set</fsummary> - <type> - <v>Element = term()</v> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Element</c> is an element of - <c>Set</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of + <c><anno>Set</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>is_set(Term) -> bool()</name> + <name name="is_set" arity="1"/> <fsummary>Test for a gb_set</fsummary> - <type> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Set</c> appears to be a gb_set, + <p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to be a gb_set, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>is_subset(Set1, Set2) -> bool()</name> + <name name="is_subset" arity="2"/> <fsummary>Test for subset</fsummary> - <type> - <v>Set1 = Set2 = gb_set()</v> - </type> <desc> - <p>Returns <c>true</c> when every element of <c>Set1</c> is - also a member of <c>Set2</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c> is + also a member of <c><anno>Set2</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>iterator(Set) -> Iter</name> + <name name="iterator" arity="1"/> <fsummary>Return an iterator for a gb_set</fsummary> - <type> - <v>Set = gb_set()</v> - <v>Iter = term()</v> - </type> <desc> <p>Returns an iterator that can be used for traversing the - entries of <c>Set</c>; see <c>next/1</c>. The implementation + entries of <c><anno>Set</anno></c>; see <c>next/1</c>. The implementation of this is very efficient; traversing the whole set using <c>next/1</c> is only slightly slower than getting the list of all elements using <c>to_list/1</c> and traversing that. @@ -361,118 +294,84 @@ gb_set() = a GB set</code> </desc> </func> <func> - <name>largest(Set) -> term()</name> + <name name="largest" arity="1"/> <fsummary>Return largest element</fsummary> - <type> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns the largest element in <c>Set</c>. Assumes that - <c>Set</c> is nonempty.</p> + <p>Returns the largest element in <c><anno>Set</anno></c>. Assumes that + <c><anno>Set</anno></c> is nonempty.</p> </desc> </func> <func> - <name>next(Iter1) -> {Element, Iter2} | none</name> + <name name="next" arity="1"/> <fsummary>Traverse a gb_set with an iterator</fsummary> - <type> - <v>Iter1 = Iter2 = Element = term()</v> - </type> <desc> - <p>Returns <c>{Element, Iter2}</c> where <c>Element</c> is the - smallest element referred to by the iterator <c>Iter1</c>, - and <c>Iter2</c> is the new iterator to be used for + <p>Returns <c>{<anno>Element</anno>, <anno>Iter2</anno>}</c> where <c><anno>Element</anno></c> is the + smallest element referred to by the iterator <c><anno>Iter1</anno></c>, + and <c><anno>Iter2</anno></c> is the new iterator to be used for traversing the remaining elements, or the atom <c>none</c> if no elements remain.</p> </desc> </func> <func> - <name>singleton(Element) -> gb_set()</name> + <name name="singleton" arity="1"/> <fsummary>Return a gb_set with one element</fsummary> - <type> - <v>Element = term()</v> - </type> <desc> - <p>Returns a gb_set containing only the element <c>Element</c>.</p> + <p>Returns a gb_set containing only the element <c><anno>Element</anno></c>.</p> </desc> </func> <func> - <name>size(Set) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of elements in a gb_set</fsummary> - <type> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns the number of elements in <c>Set</c>.</p> + <p>Returns the number of elements in <c><anno>Set</anno></c>.</p> </desc> </func> <func> - <name>smallest(Set) -> term()</name> + <name name="smallest" arity="1"/> <fsummary>Return smallest element</fsummary> - <type> - <v>Set = gb_set()</v> - </type> <desc> - <p>Returns the smallest element in <c>Set</c>. Assumes that - <c>Set</c> is nonempty.</p> + <p>Returns the smallest element in <c><anno>Set</anno></c>. Assumes that + <c><anno>Set</anno></c> is nonempty.</p> </desc> </func> <func> - <name>take_largest(Set1) -> {Element, Set2}</name> + <name name="take_largest" arity="1"/> <fsummary>Extract largest element</fsummary> - <type> - <v>Set1 = Set2 = gb_set()</v> - <v>Element = term()</v> - </type> <desc> - <p>Returns <c>{Element, Set2}</c>, where <c>Element</c> is the - largest element in <c>Set1</c>, and <c>Set2</c> is this set - with <c>Element</c> deleted. Assumes that <c>Set1</c> is + <p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where <c><anno>Element</anno></c> is the + largest element in <c><anno>Set1</anno></c>, and <c><anno>Set2</anno></c> is this set + with <c><anno>Element</anno></c> deleted. Assumes that <c><anno>Set1</anno></c> is nonempty.</p> </desc> </func> <func> - <name>take_smallest(Set1) -> {Element, Set2}</name> + <name name="take_smallest" arity="1"/> <fsummary>Extract smallest element</fsummary> - <type> - <v>Set1 = Set2 = gb_set()</v> - <v>Element = term()</v> - </type> <desc> - <p>Returns <c>{Element, Set2}</c>, where <c>Element</c> is the - smallest element in <c>Set1</c>, and <c>Set2</c> is this set - with <c>Element</c> deleted. Assumes that <c>Set1</c> is + <p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where <c><anno>Element</anno></c> is the + smallest element in <c><anno>Set1</anno></c>, and <c><anno>Set2</anno></c> is this set + with <c><anno>Element</anno></c> deleted. Assumes that <c><anno>Set1</anno></c> is nonempty.</p> </desc> </func> <func> - <name>to_list(Set) -> List</name> + <name name="to_list" arity="1"/> <fsummary>Convert a gb_set into a list</fsummary> - <type> - <v>Set = gb_set()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns the elements of <c>Set</c> as a list.</p> + <p>Returns the elements of <c><anno>Set</anno></c> as a list.</p> </desc> </func> <func> - <name>union(Set1, Set2) -> Set3</name> + <name name="union" arity="2"/> <fsummary>Return the union of two gb_sets</fsummary> - <type> - <v>Set1 = Set2 = Set3 = gb_set()</v> - </type> <desc> - <p>Returns the merged (union) gb_set of <c>Set1</c> and - <c>Set2</c>.</p> + <p>Returns the merged (union) gb_set of <c><anno>Set1</anno></c> and + <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>union(SetList) -> Set</name> + <name name="union" arity="1"/> <fsummary>Return the union of a list of gb_sets</fsummary> - <type> - <v>SetList = [gb_set()]</v> - <v>Set = gb_set()</v> - </type> <desc> <p>Returns the merged (union) gb_set of the list of gb_sets.</p> </desc> diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml index 94f40c28bd..65c866efbe 100644 --- a/lib/stdlib/doc/src/gb_trees.xml +++ b/lib/stdlib/doc/src/gb_trees.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2010</year> + <year>2001</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -57,20 +57,22 @@ trees. Behaviour is logarithmic (as it should be).</p> </section> - <section> - <title>DATA TYPES</title> - <code type="none"> -gb_tree() = a GB tree</code> - </section> + <datatypes> + <datatype> + <name><marker id="type-gb_tree">gb_tree()</marker></name> + <desc><p>A GB tree.</p></desc> + </datatype> + <datatype> + <name name="iter"/> + <desc><p>A GB tree iterator.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>balance(Tree1) -> Tree2</name> + <name name="balance" arity="1"/> <fsummary>Rebalance a tree</fsummary> - <type> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Rebalances <c>Tree1</c>. Note that this is rarely necessary, + <p>Rebalances <c><anno>Tree1</anno></c>. Note that this is rarely necessary, but may be motivated when a large number of nodes have been deleted from the tree without further insertions. Rebalancing could then be forced in order to minimise lookup times, since @@ -78,139 +80,97 @@ gb_tree() = a GB tree</code> </desc> </func> <func> - <name>delete(Key, Tree1) -> Tree2</name> + <name name="delete" arity="2"/> <fsummary>Remove a node from a tree</fsummary> - <type> - <v>Key = term()</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Removes the node with key <c>Key</c> from <c>Tree1</c>; + <p>Removes the node with key <c><anno>Key</anno></c> from <c><anno>Tree1</anno></c>; returns new tree. Assumes that the key is present in the tree, crashes otherwise.</p> </desc> </func> <func> - <name>delete_any(Key, Tree1) -> Tree2</name> + <name name="delete_any" arity="2"/> <fsummary>Remove a (possibly non-existing) node from a tree</fsummary> - <type> - <v>Key = term()</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Removes the node with key <c>Key</c> from <c>Tree1</c> if + <p>Removes the node with key <c><anno>Key</anno></c> from <c><anno>Tree1</anno></c> if the key is present in the tree, otherwise does nothing; returns new tree.</p> </desc> </func> <func> - <name>empty() -> Tree</name> + <name name="empty" arity="0"/> <fsummary>Return an empty tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - </type> <desc> <p>Returns a new empty tree</p> </desc> </func> <func> - <name>enter(Key, Val, Tree1) -> Tree2</name> + <name name="enter" arity="3"/> <fsummary>Insert or update key with value in a tree</fsummary> - <type> - <v>Key = Val = term()</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Inserts <c>Key</c> with value <c>Val</c> into <c>Tree1</c> if + <p>Inserts <c><anno>Key</anno></c> with value <c><anno>Val</anno></c> into <c><anno>Tree1</anno></c> if the key is not present in the tree, otherwise updates - <c>Key</c> to value <c>Val</c> in <c>Tree1</c>. Returns the + <c><anno>Key</anno></c> to value <c><anno>Val</anno></c> in <c><anno>Tree1</anno></c>. Returns the new tree.</p> </desc> </func> <func> - <name>from_orddict(List) -> Tree</name> + <name name="from_orddict" arity="1"/> <fsummary>Make a tree from an orddict</fsummary> - <type> - <v>List = [{Key, Val}]</v> - <v> Key = Val = term()</v> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Turns an ordered list <c>List</c> of key-value tuples into a + <p>Turns an ordered list <c><anno>List</anno></c> of key-value tuples into a tree. The list must not contain duplicate keys.</p> </desc> </func> <func> - <name>get(Key, Tree) -> Val</name> + <name name="get" arity="2"/> <fsummary>Look up a key in a tree, if present</fsummary> - <type> - <v>Key = Val = term()</v> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Retrieves the value stored with <c>Key</c> in <c>Tree</c>. + <p>Retrieves the value stored with <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>. Assumes that the key is present in the tree, crashes otherwise.</p> </desc> </func> <func> - <name>lookup(Key, Tree) -> {value, Val} | none</name> + <name name="lookup" arity="2"/> <fsummary>Look up a key in a tree</fsummary> - <type> - <v>Key = Val = term()</v> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Looks up <c>Key</c> in <c>Tree</c>; returns - <c>{value, Val}</c>, or <c>none</c> if <c>Key</c> is not + <p>Looks up <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>; returns + <c>{value, <anno>Val</anno>}</c>, or <c>none</c> if <c><anno>Key</anno></c> is not present.</p> </desc> </func> <func> - <name>insert(Key, Val, Tree1) -> Tree2</name> + <name name="insert" arity="3"/> <fsummary>Insert a new key and value in a tree</fsummary> - <type> - <v>Key = Val = term()</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Inserts <c>Key</c> with value <c>Val</c> into <c>Tree1</c>; + <p>Inserts <c><anno>Key</anno></c> with value <c><anno>Val</anno></c> into <c><anno>Tree1</anno></c>; returns the new tree. Assumes that the key is not present in the tree, crashes otherwise.</p> </desc> </func> <func> - <name>is_defined(Key, Tree) -> bool()</name> + <name name="is_defined" arity="2"/> <fsummary>Test for membership of a tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Key</c> is present in <c>Tree</c>, + <p>Returns <c>true</c> if <c><anno>Key</anno></c> is present in <c><anno>Tree</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>is_empty(Tree) -> bool()</name> + <name name="is_empty" arity="1"/> <fsummary>Test for empty tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Tree</c> is an empty tree, and + <p>Returns <c>true</c> if <c><anno>Tree</anno></c> is an empty tree, and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>iterator(Tree) -> Iter</name> + <name name="iterator" arity="1"/> <fsummary>Return an iterator for a tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Iter = term()</v> - </type> <desc> <p>Returns an iterator that can be used for traversing the - entries of <c>Tree</c>; see <c>next/1</c>. The implementation + entries of <c><anno>Tree</anno></c>; see <c>next/1</c>. The implementation of this is very efficient; traversing the whole tree using <c>next/1</c> is only slightly slower than getting the list of all elements using <c>to_list/1</c> and traversing that. @@ -220,141 +180,99 @@ gb_tree() = a GB tree</code> </desc> </func> <func> - <name>keys(Tree) -> [Key]</name> + <name name="keys" arity="1"/> <fsummary>Return a list of the keys in a tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Key = term()</v> - </type> <desc> - <p>Returns the keys in <c>Tree</c> as an ordered list.</p> + <p>Returns the keys in <c><anno>Tree</anno></c> as an ordered list.</p> </desc> </func> <func> - <name>largest(Tree) -> {Key, Val}</name> + <name name="largest" arity="1"/> <fsummary>Return largest key and value</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Key = Val = term()</v> - </type> <desc> - <p>Returns <c>{Key, Val}</c>, where <c>Key</c> is the largest - key in <c>Tree</c>, and <c>Val</c> is the value associated + <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>}</c>, where <c><anno>Key</anno></c> is the largest + key in <c><anno>Tree</anno></c>, and <c><anno>Val</anno></c> is the value associated with this key. Assumes that the tree is nonempty.</p> </desc> </func> <func> - <name>map(Function, Tree1) -> Tree2</name> + <name name="map" arity="2"/> <fsummary>Return largest key and value</fsummary> - <type> - <v>Function = fun(K, V1) -> V2</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> - <desc><p>maps the function F(K, V1) -> V2 to all key-value pairs - of the tree Tree1 and returns a new tree Tree2 with the same set of keys - as Tree1 and the new set of values V2.</p> + <desc><p>Maps the function F(<anno>K</anno>, <anno>V1</anno>) -> <anno>V2</anno> to all key-value pairs + of the tree <c><anno>Tree1</anno></c> and returns a new tree <c><anno>Tree2</anno></c> with the same set of keys + as <c><anno>Tree1</anno></c> and the new set of values <c><anno>V2</anno></c>.</p> </desc> </func> <func> - <name>next(Iter1) -> {Key, Val, Iter2} | none</name> + <name name="next" arity="1"/> <fsummary>Traverse a tree with an iterator</fsummary> - <type> - <v>Iter1 = Iter2 = Key = Val = term()</v> - </type> <desc> - <p>Returns <c>{Key, Val, Iter2}</c> where <c>Key</c> is the - smallest key referred to by the iterator <c>Iter1</c>, and - <c>Iter2</c> is the new iterator to be used for + <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Iter2</anno>}</c> where <c><anno>Key</anno></c> is the + smallest key referred to by the iterator <c><anno>Iter1</anno></c>, and + <c><anno>Iter2</anno></c> is the new iterator to be used for traversing the remaining nodes, or the atom <c>none</c> if no nodes remain.</p> </desc> </func> <func> - <name>size(Tree) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of nodes in a tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - </type> <desc> - <p>Returns the number of nodes in <c>Tree</c>.</p> + <p>Returns the number of nodes in <c><anno>Tree</anno></c>.</p> </desc> </func> <func> - <name>smallest(Tree) -> {Key, Val}</name> + <name name="smallest" arity="1"/> <fsummary>Return smallest key and value</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Key = Val = term()</v> - </type> <desc> - <p>Returns <c>{Key, Val}</c>, where <c>Key</c> is the smallest - key in <c>Tree</c>, and <c>Val</c> is the value associated + <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>}</c>, where <c><anno>Key</anno></c> is the smallest + key in <c><anno>Tree</anno></c>, and <c><anno>Val</anno></c> is the value associated with this key. Assumes that the tree is nonempty.</p> </desc> </func> <func> - <name>take_largest(Tree1) -> {Key, Val, Tree2}</name> + <name name="take_largest" arity="1"/> <fsummary>Extract largest key and value</fsummary> - <type> - <v>Tree1 = Tree2 = gb_tree()</v> - <v>Key = Val = term()</v> - </type> <desc> - <p>Returns <c>{Key, Val, Tree2}</c>, where <c>Key</c> is the - largest key in <c>Tree1</c>, <c>Val</c> is the value - associated with this key, and <c>Tree2</c> is this tree with + <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Tree2</anno>}</c>, where <c><anno>Key</anno></c> is the + largest key in <c><anno>Tree1</anno></c>, <c><anno>Val</anno></c> is the value + associated with this key, and <c><anno>Tree2</anno></c> is this tree with the corresponding node deleted. Assumes that the tree is nonempty.</p> </desc> </func> <func> - <name>take_smallest(Tree1) -> {Key, Val, Tree2}</name> + <name name="take_smallest" arity="1"/> <fsummary>Extract smallest key and value</fsummary> - <type> - <v>Tree1 = Tree2 = gb_tree()</v> - <v>Key = Val = term()</v> - </type> <desc> - <p>Returns <c>{Key, Val, Tree2}</c>, where <c>Key</c> is the - smallest key in <c>Tree1</c>, <c>Val</c> is the value - associated with this key, and <c>Tree2</c> is this tree with + <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Tree2</anno>}</c>, where <c><anno>Key</anno></c> is the + smallest key in <c><anno>Tree1</anno></c>, <c><anno>Val</anno></c> is the value + associated with this key, and <c><anno>Tree2</anno></c> is this tree with the corresponding node deleted. Assumes that the tree is nonempty.</p> </desc> </func> <func> - <name>to_list(Tree) -> [{Key, Val}]</name> + <name name="to_list" arity="1"/> <fsummary>Convert a tree into a list</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Key = Val = term()</v> - </type> <desc> <p>Converts a tree into an ordered list of key-value tuples.</p> </desc> </func> <func> - <name>update(Key, Val, Tree1) -> Tree2</name> + <name name="update" arity="3"/> <fsummary>Update a key to new value in a tree</fsummary> - <type> - <v>Key = Val = term()</v> - <v>Tree1 = Tree2 = gb_tree()</v> - </type> <desc> - <p>Updates <c>Key</c> to value <c>Val</c> in <c>Tree1</c>; + <p>Updates <c><anno>Key</anno></c> to value <c><anno>Val</anno></c> in <c><anno>Tree1</anno></c>; returns the new tree. Assumes that the key is present in the tree.</p> </desc> </func> <func> - <name>values(Tree) -> [Val]</name> + <name name="values" arity="1"/> <fsummary>Return a list of the values in a tree</fsummary> - <type> - <v>Tree = gb_tree()</v> - <v>Val = term()</v> - </type> <desc> - <p>Returns the values in <c>Tree</c> as an ordered list, sorted + <p>Returns the values in <c><anno>Tree</anno></c> as an ordered list, sorted by their corresponding keys. Duplicates are not removed.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 2234a62ac3..24bcb419fe 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -100,6 +100,20 @@ gen_event:stop -----> Module:terminate/2 the specified event manager does not exist or if bad arguments are given.</p> </description> + <datatypes> + <datatype> + <name name="handler"/> + </datatype> + <datatype> + <name name="handler_args"/> + </datatype> + <datatype> + <name name="add_handler_ret"/> + </datatype> + <datatype> + <name name="del_handler_ret"/> + </datatype> + </datatypes> <funcs> <func> <name>start_link() -> Result</name> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index d15383c621..421eeb4fd3 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -430,7 +430,6 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 denote a state of the state machine. <em>state data</em> is used to denote the internal state of the Erlang process which implements the state machine.</p> - <p></p> </section> <funcs> <func> @@ -438,7 +437,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <fsummary>Initialize process and internal state name and state data.</fsummary> <type> <v>Args = term()</v> - <v>Return = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> + <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> <v> | {ok,StateName,StateData,hibernate}</v> <v> | {stop,Reason} | ignore</v> <v> StateName = atom()</v> @@ -639,9 +638,9 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 <v>StateName = atom()</v> <v>StateData = term()</v> <v>Result = {next_state,NextStateName,NewStateData}</v> - <v> > | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> > | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> > | {stop,Reason,NewStateData}</v> + <v> | {next_state,NextStateName,NewStateData,Timeout}</v> + <v> | {next_state,NextStateName,NewStateData,hibernate}</v> + <v> | {stop,Reason,NewStateData}</v> <v> NextStateName = atom()</v> <v> NewStateData = term()</v> <v> Timeout = int()>0 | infinity</v> diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index 41e3e92c59..667d758e29 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -43,7 +43,7 @@ <p>As of R13A, data supplied to the <seealso marker="#put_chars/2">put_chars</seealso> function should be in the - <c>chardata()</c> format described below. This means that programs + <seealso marker="unicode#type-chardata"><c>unicode:chardata()</c></seealso> format. This means that programs supplying binaries to this function need to convert them to UTF-8 before trying to output the data on an <c>io_device()</c>.</p> @@ -64,76 +64,84 @@ </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -io_device() - as returned by file:open/2, a process handling IO protocols</code> - - <code type="none"> -unicode_binary() = binary() with characters encoded in UTF-8 coding standard -unicode_char() = integer() representing valid unicode codepoint - -chardata() = charlist() | unicode_binary() + <datatypes> + <datatype> + <name name="device"/> + <desc> + <p>Either <c>standard_io</c>, <c>standard_error</c>, a + registered name, or a pid handling IO protocols (returned from + <seealso marker="file#open/2">file:open/2</seealso>).</p> + </desc> + </datatype> + <datatype> + <name name="opt_pair"/> + </datatype> + <datatype> + <name name="expand_fun"/> + </datatype> + <datatype> + <name name="encoding"/> + </datatype> + <datatype> + <name name="setopt"/> + </datatype> + <datatype> + <name name="format"/> + </datatype> + <datatype> + <name name="line"/> + </datatype> + <datatype> + <name name="prompt"/> + </datatype> + <datatype> + <name name="request_error"/> + </datatype> + <datatype> + <name name="error_description"/> + <desc><p>Whatever the I/O-server sends.</p></desc> + </datatype> + </datatypes> -charlist() = [unicode_char() | unicode_binary() | charlist()] - a unicode_binary is allowed as the tail of the list</code> - </section> <funcs> <func> - <name>columns() -> {ok,int()} | {error, enotsup}</name> - <name>columns(IoDevice) -> {ok,int()} | {error, enotsup}</name> + <name name="columns" arity="0"/> + <name name="columns" arity="1"/> <fsummary>Get the number of columns of a device</fsummary> - <type> - <v>IoDevice = io_device()</v> - </type> <desc> <p>Retrieves the number of columns of the - <c>IoDevice</c> (i.e. the width of a terminal). The function + <c><anno>IoDevice</anno></c> (i.e. the width of a terminal). The function only succeeds for terminal devices, for all other devices the function returns <c>{error, enotsup}</c></p> </desc> </func> <func> - <name>put_chars(IoData) -> ok</name> - <name>put_chars(IoDevice, IoData) -> ok</name> + <name name="put_chars" arity="1"/> + <name name="put_chars" arity="2"/> <fsummary>Write a list of characters</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>IoData = chardata()</v> - </type> <desc> - <p>Writes the characters of <c>IoData</c> to the io_server() - (<c>IoDevice</c>).</p> + <p>Writes the characters of <c><anno>CharData</anno></c> to the io_server() + (<c><anno>IoDevice</anno></c>).</p> </desc> </func> <func> - <name>nl() -> ok</name> - <name>nl(IoDevice) -> ok</name> + <name name="nl" arity="0"/> + <name name="nl" arity="1"/> <fsummary>Write a newline</fsummary> - <type> - <v>IoDevice = io_device()</v> - </type> <desc> - <p>Writes new line to the standard output (<c>IoDevice</c>).</p> + <p>Writes new line to the standard output (<c><anno>IoDevice</anno></c>).</p> </desc> </func> <func> - <name>get_chars(Prompt, Count) -> Data | eof</name> - <name>get_chars(IoDevice, Prompt, Count) -> Data | eof</name> + <name name="get_chars" arity="2"/> + <name name="get_chars" arity="3"/> <fsummary>Read a specified number of characters</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>Count = int()</v> - <v>Data = [ unicode_char() ] | unicode_binary()</v> - </type> <desc> - <p>Reads <c>Count</c> characters from standard input - (<c>IoDevice</c>), prompting it with <c>Prompt</c>. It + <p>Reads <c><anno>Count</anno></c> characters from standard input + (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It returns:</p> <taglist> - <tag><c>Data</c></tag> + <tag><c><anno>Data</anno></c></tag> <item> <p>The input characters. If the device supports Unicode, the data may represent codepoints larger than 255 (the @@ -145,7 +153,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] <item> <p>End of file was encountered.</p> </item> - <tag><c>{error,Reason}</c></tag> + <tag><c>{error,<anno>Reason</anno>}</c></tag> <item> <p>Other (rare) error condition, for instance <c>{error,estale}</c> if reading from an NFS file system.</p> @@ -154,19 +162,14 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>get_line(Prompt) -> Data | eof | {error,Reason}</name> - <name>get_line(IoDevice, Prompt) -> Data | eof | {error,Reason}</name> + <name name="get_line" arity="1"/> + <name name="get_line" arity="2"/> <fsummary>Read a line</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>Data = [ unicode_char() ] | unicode_binary()</v> - </type> <desc> - <p>Reads a line from the standard input (<c>IoDevice</c>), - prompting it with <c>Prompt</c>. It returns:</p> + <p>Reads a line from the standard input (<c><anno>IoDevice</anno></c>), + prompting it with <c><anno>Prompt</anno></c>. It returns:</p> <taglist> - <tag><c>Data</c></tag> + <tag><c><anno>Data</anno></c></tag> <item> <p>The characters in the line terminated by a LF (or end of file). If the device supports Unicode, @@ -179,7 +182,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] <item> <p>End of file was encountered.</p> </item> - <tag><c>{error,Reason}</c></tag> + <tag><c>{error,<anno>Reason</anno>}</c></tag> <item> <p>Other (rare) error condition, for instance <c>{error,estale}</c> if reading from an NFS file system.</p> @@ -188,15 +191,9 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>getopts() -> Opts</name> - <name>getopts(IoDevice) -> Opts</name> + <name name="getopts" arity="0"/> + <name name="getopts" arity="1"/> <fsummary>Get the supported options and values from an I/O-server</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Opts = [Opt]</v> - <v> Opt = {atom(),Value}</v> - <v> Value = term()</v> - </type> <desc> <p>This function requests all available options and their current values for a specific io_device(). Example:</p> <pre> @@ -216,18 +213,11 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>setopts(Opts) -> ok | {error, Reason}</name> - <name>setopts(IoDevice, Opts) -> ok | {error, Reason}</name> + <name name="setopts" arity="1"/> + <name name="setopts" arity="2"/> <fsummary>Set options</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Opts = [Opt]</v> - <v> Opt = atom() | {atom(),Value}</v> - <v> Value = term()</v> - <v>Reason = term()</v> - </type> <desc> - <p>Set options for the io_device() (<c>IoDevice</c>).</p> + <p>Set options for the io_device() (<c><anno>IoDevice</anno></c>).</p> <p>Possible options and values vary depending on the actual io_device(). For a list of supported options and their current values @@ -236,17 +226,17 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] <p>The options and values supported by the current OTP io_devices are:</p> <taglist> - <tag><c>binary, list or {binary, bool()}</c></tag> + <tag><c>binary, list or {binary, boolean()}</c></tag> <item> <p>If set in binary mode (binary or {binary,true}), the io_server() sends binary data (encoded in UTF-8) as answers to the get_line, get_chars and, if possible, get_until requests (see the I/O protocol description in STDLIB User's Guide for details). The immediate effect is that <c>get_chars/2,3</c> and <c>get_line/1,2</c> return UTF-8 binaries instead of lists of chars for the affected device.</p> <p>By default, all io_devices in OTP are set in list mode, but the io functions can handle any of these modes and so should other, user written, modules behaving as clients to I/O-servers.</p> <p>This option is supported by the standard shell (group.erl), the 'oldshell' (user.erl) and the file I/O servers.</p> </item> - <tag><c>{echo, bool()}</c></tag> + <tag><c>{echo, boolean()}</c></tag> <item> <p>Denotes if the terminal should echo input. Only supported for the standard shell I/O-server (group.erl)</p> </item> - <tag><c>{expand_fun, fun()}</c></tag> + <tag><c>{expand_fun, expand_fun()}</c></tag> <item> <p>Provide a function for tab-completion (expansion) like the erlang shell. This function is called @@ -288,35 +278,24 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>write(Term) -> ok</name> - <name>write(IoDevice, Term) -> ok</name> + <name name="write" arity="1"/> + <name name="write" arity="2"/> <fsummary>Write a term</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Term = term()</v> - </type> <desc> - <p>Writes the term <c>Term</c> to the standard output - (<c>IoDevice</c>).</p> + <p>Writes the term <c><anno>Term</anno></c> to the standard output + (<c><anno>IoDevice</anno></c>).</p> </desc> </func> <func> - <name>read(Prompt) -> Result</name> - <name>read(IoDevice, Prompt) -> Result</name> + <name name="read" arity="1"/> + <name name="read" arity="2"/> <fsummary>Read a term</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>Result = {ok, Term} | eof | {error, ErrorInfo}</v> - <v> Term = term()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> - <p>Reads a term <c>Term</c> from the standard input - (<c>IoDevice</c>), prompting it with <c>Prompt</c>. It + <p>Reads a term <c><anno>Term</anno></c> from the standard input + (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It returns:</p> <taglist> - <tag><c>{ok, Term}</c></tag> + <tag><c>{ok, <anno>Term</anno>}</c></tag> <item> <p>The parsing was successful.</p> </item> @@ -324,7 +303,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, ErrorInfo}</c></tag> + <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag> <item> <p>The parsing failed.</p> </item> @@ -332,31 +311,22 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>read(IoDevice, Prompt, StartLine) -> Result</name> + <name name="read" arity="3"/> <fsummary>Read a term</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>StartLine = int()</v> - <v>Result = {ok, Term, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v> - <v> Term = term()</v> - <v> EndLine = int()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> - <p>Reads a term <c>Term</c> from <c>IoDevice</c>, prompting it - with <c>Prompt</c>. Reading starts at line number - <c>StartLine</c>. It returns:</p> + <p>Reads a term <c><anno>Term</anno></c> from <c><anno>IoDevice</anno></c>, prompting it + with <c><anno>Prompt</anno></c>. Reading starts at line number + <c><anno>StartLine</anno></c>. It returns:</p> <taglist> - <tag><c>{ok, Term, EndLine}</c></tag> + <tag><c>{ok, Term, <anno>EndLine</anno>}</c></tag> <item> <p>The parsing was successful.</p> </item> - <tag><c>{eof, EndLine}</c></tag> + <tag><c>{eof, <anno>EndLine</anno>}</c></tag> <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, ErrorInfo, EndLine}</c></tag> + <tag><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLine</anno>}</c></tag> <item> <p>The parsing failed.</p> </item> @@ -364,24 +334,19 @@ charlist() = [unicode_char() | unicode_binary() | charlist()] </desc> </func> <func> - <name>fwrite(Format) -></name> - <name>fwrite(Format, Data) -> ok</name> - <name>fwrite(IoDevice, Format, Data) -> ok</name> - <name>format(Format) -></name> - <name>format(Format, Data) -> ok</name> - <name>format(IoDevice, Format, Data) -> ok</name> + <name name="fwrite" arity="1"/> + <name name="fwrite" arity="2"/> + <name name="fwrite" arity="3"/> + <name name="format" arity="1"/> + <name name="format" arity="2"/> + <name name="format" arity="3"/> <fsummary>Write formatted output</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Format = atom() | string() | binary()</v> - <v>Data = [term()]</v> - </type> <desc> - <p>Writes the items in <c>Data</c> (<c>[]</c>) on the standard - output (<c>IoDevice</c>) in accordance with <c>Format</c>. - <c>Format</c> contains plain characters which are copied to + <p>Writes the items in <c><anno>Data</anno></c> (<c>[]</c>) on the standard + output (<c><anno>IoDevice</anno></c>) in accordance with <c><anno>Format</anno></c>. + <c><anno>Format</anno></c> contains plain characters which are copied to the output device, and control sequences for formatting, see - below. If <c>Format</c> is an atom or a binary, it is first + below. If <c><anno>Format</anno></c> is an atom or a binary, it is first converted to a list with the aid of <c>atom_to_list/1</c> or <c>binary_to_list/1</c>.</p> <pre> @@ -474,7 +439,7 @@ ok</pre> <item> <p>Prints the argument with the <c>string</c> syntax. The argument is, if no Unicode translation modifier is present, an - <seealso marker="erts:erlang#iolist_definition">I/O list</seealso>, a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is chardata(), meaning that binaries are in UTF-8. The characters + iolist(), a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters are printed without quotes. The string is first truncated by the given precision and then padded and justified to the given field width. The default precision is the field width.</p> @@ -673,23 +638,15 @@ ok </desc> </func> <func> - <name>fread(Prompt, Format) -> Result</name> - <name>fread(IoDevice, Prompt, Format) -> Result</name> + <name name="fread" arity="2"/> + <name name="fread" arity="3"/> <fsummary>Read formatted input</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>Format = string()</v> - <v>Result = {ok, Terms} | eof | {error, What}</v> - <v> Terms = [term()]</v> - <v> What = term()</v> - </type> <desc> - <p>Reads characters from the standard input (<c>IoDevice</c>), - prompting it with <c>Prompt</c>. Interprets the characters in - accordance with <c>Format</c>. <c>Format</c> contains control + <p>Reads characters from the standard input (<c><anno>IoDevice</anno></c>), + prompting it with <c><anno>Prompt</anno></c>. Interprets the characters in + accordance with <c><anno>Format</anno></c>. <c><anno>Format</anno></c> contains control sequences which directs the interpretation of the input.</p> - <p><c>Format</c> may contain:</p> + <p><c><anno>Format</anno></c> may contain:</p> <list type="bulleted"> <item> <p>White space characters (SPACE, TAB and NEWLINE) which @@ -803,19 +760,19 @@ Prompt> <input><Character beyond latin1 range not printable in this medium> </taglist> <p>It returns:</p> <taglist> - <tag><c>{ok, Terms}</c></tag> + <tag><c>{ok, <anno>Terms</anno>}</c></tag> <item> - <p>The read was successful and <c>Terms</c> is the list + <p>The read was successful and <c><anno>Terms</anno></c> is the list of successfully matched and read items.</p> </item> <tag><c>eof</c></tag> <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, What}</c></tag> + <tag><c>{error, <anno>What</anno>}</c></tag> <item> <p>The read operation failed and the parameter - <c>What</c> gives a hint about the error.</p> + <c><anno>What</anno></c> gives a hint about the error.</p> </item> </taglist> </item> @@ -834,33 +791,21 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in </desc> </func> <func> - <name>rows() -> {ok,int()} | {error, enotsup}</name> - <name>rows(IoDevice) -> {ok,int()} | {error, enotsup}</name> + <name name="rows" arity="0"/> + <name name="rows" arity="1"/> <fsummary>Get the number of rows of a device</fsummary> - <type> - <v>IoDevice = io_device()</v> - </type> <desc> <p>Retrieves the number of rows of the - <c>IoDevice</c> (i.e. the height of a terminal). The function + <c><anno>IoDevice</anno></c> (i.e. the height of a terminal). The function only succeeds for terminal devices, for all other devices the function returns <c>{error, enotsup}</c></p> </desc> </func> <func> - <name>scan_erl_exprs(Prompt) -></name> - <name>scan_erl_exprs(Prompt, StartLine) -> Result</name> - <name>scan_erl_exprs(IoDevice, Prompt, StartLine) -> Result</name> + <name name="scan_erl_exprs" arity="1"/> + <name name="scan_erl_exprs" arity="2"/> + <name name="scan_erl_exprs" arity="3"/> <fsummary>Read and tokenize Erlang expressions</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>StartLine = int()</v> - <v>Result = {ok, Tokens, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v> - <v> Tokens -- see erl_scan(3)</v> - <v> EndLine = int()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> <p>Reads data from the standard input (<c>IoDevice</c>), prompting it with <c>Prompt</c>. Reading starts at line number @@ -876,7 +821,7 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, ErrorInfo, EndLine}</c></tag> + <tag><c>{error, ErrorInfo, ErrorLine}</c></tag> <item> <p>An error occurred.</p> </item> @@ -892,23 +837,14 @@ enter><input>1.0er.</input> </desc> </func> <func> - <name>scan_erl_form(Prompt) -></name> - <name>scan_erl_form(Prompt, StartLine) -> Result</name> - <name>scan_erl_form(IoDevice, Prompt, StartLine) -> Result</name> + <name name="scan_erl_form" arity="1"/> + <name name="scan_erl_form" arity="2"/> + <name name="scan_erl_form" arity="3"/> <fsummary>Read and tokenize an Erlang form</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>StartLine = int()</v> - <v>Result = {ok, Tokens, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v> - <v> Tokens -- see erl_scan(3)</v> - <v> EndLine = int()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> - <p>Reads data from the standard input (<c>IoDevice</c>), - prompting it with <c>Prompt</c>. Starts reading at line number - <c>StartLine</c> (1). The data is tokenized as if it were an + <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), + prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number + <c><anno>StartLine</anno></c> (1). The data is tokenized as if it were an Erlang form - one of the valid Erlang expressions in an Erlang source file - until a final <c>'.'</c> is reached. This last token is also returned. The return values are the @@ -916,27 +852,19 @@ enter><input>1.0er.</input> </desc> </func> <func> - <name>parse_erl_exprs(Prompt) -></name> - <name>parse_erl_exprs(Prompt, StartLine) -> Result</name> - <name>parse_erl_exprs(IoDevice, Prompt, StartLine) -> Result</name> + <name name="parse_erl_exprs" arity="1"/> + <name name="parse_erl_exprs" arity="2"/> + <name name="parse_erl_exprs" arity="3"/> + <type name="parse_ret"/> <fsummary>Read, tokenize and parse Erlang expressions</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>StartLine = int()</v> - <v>Result = {ok, Expr_list, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v> - <v> Expr_list -- see erl_parse(3)</v> - <v> EndLine = int()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> - <p>Reads data from the standard input (<c>IoDevice</c>), - prompting it with <c>Prompt</c>. Starts reading at line number - <c>StartLine</c> (1). The data is tokenized and parsed as if + <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), + prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number + <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if it were a sequence of Erlang expressions until a final '.' is reached. It returns:</p> <taglist> - <tag><c>{ok, Expr_list, EndLine}</c></tag> + <tag><c>{ok, ExprList, EndLine}</c></tag> <item> <p>The parsing was successful.</p> </item> @@ -944,7 +872,7 @@ enter><input>1.0er.</input> <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, ErrorInfo, EndLine}</c></tag> + <tag><c>{error, ErrorInfo, ErrorLine}</c></tag> <item> <p>An error occurred.</p> </item> @@ -960,23 +888,15 @@ enter><input>abc("hey".</input> </desc> </func> <func> - <name>parse_erl_form(Prompt) -></name> - <name>parse_erl_form(Prompt, StartLine) -> Result</name> - <name>parse_erl_form(IoDevice, Prompt, StartLine) -> Result</name> + <name name="parse_erl_form" arity="1"/> + <name name="parse_erl_form" arity="2"/> + <name name="parse_erl_form" arity="3"/> + <type name="parse_form_ret"/> <fsummary>Read, tokenize and parse an Erlang form</fsummary> - <type> - <v>IoDevice = io_device()</v> - <v>Prompt = atom() | string()</v> - <v>StartLine = int()</v> - <v>Result = {ok, AbsForm, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v> - <v> AbsForm -- see erl_parse(3)</v> - <v> EndLine = int()</v> - <v> ErrorInfo -- see section Error Information below</v> - </type> <desc> - <p>Reads data from the standard input (<c>IoDevice</c>), - prompting it with <c>Prompt</c>. Starts reading at line number - <c>StartLine</c> (1). The data is tokenized and parsed as if + <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>), + prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number + <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if it were an Erlang form - one of the valid Erlang expressions in an Erlang source file - until a final '.' is reached. It returns:</p> @@ -989,7 +909,7 @@ enter><input>abc("hey".</input> <item> <p>End of file was encountered.</p> </item> - <tag><c>{error, ErrorInfo, EndLine}</c></tag> + <tag><c>{error, ErrorInfo, ErrorLine}</c></tag> <item> <p>An error occurred.</p> </item> diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml index 399f968c5f..506c1792f1 100644 --- a/lib/stdlib/doc/src/io_lib.xml +++ b/lib/stdlib/doc/src/io_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -38,14 +38,22 @@ flattening deep lists.</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -chars() = [char() | chars()]</code> - </section> + <datatypes> + <datatype> + <name name="chars"/> + </datatype> + <datatype> + <name name="continuation"/> + <desc><p>A continuation as returned by <seealso marker="#fread/3"><c>fread/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="depth"/> + </datatype> + </datatypes> <funcs> <func> - <name>nl() -> chars()</name> + <name name="nl" arity="0"/> <fsummary>Write a newline</fsummary> <desc> <p>Returns a character list which represents a new line @@ -53,16 +61,12 @@ chars() = [char() | chars()]</code> </desc> </func> <func> - <name>write(Term) -></name> - <name>write(Term, Depth) -> chars()</name> + <name name="write" arity="1"/> + <name name="write" arity="2"/> <fsummary>Write a term</fsummary> - <type> - <v>Term = term()</v> - <v>Depth = int()</v> - </type> <desc> - <p>Returns a character list which represents <c>Term</c>. The - <c>Depth</c> (-1) argument controls the depth of the + <p>Returns a character list which represents <c><anno>Term</anno></c>. The + <c><anno>Depth</anno></c> (-1) argument controls the depth of the structures written. When the specified depth is reached, everything below this level is replaced by "...". For example:</p> @@ -74,36 +78,26 @@ chars() = [char() | chars()]</code> </desc> </func> <func> - <name>print(Term) -></name> - <name>print(Term, Column, LineLength, Depth) -> chars()</name> + <name name="print" arity="1"/> + <name name="print" arity="4"/> <fsummary>Pretty print a term</fsummary> - <type> - <v>Term = term()</v> - <v>Column = LineLenght = Depth = int()</v> - </type> <desc> <p>Also returns a list of characters which represents - <c>Term</c>, but breaks representations which are longer than + <c><anno>Term</anno></c>, but breaks representations which are longer than one line into many lines and indents each line sensibly. It also tries to detect and output lists of printable characters - as strings. <c>Column</c> is the starting column (1), - <c>LineLength</c> the maximum line length (80), and - <c>Depth</c> (-1) the maximum print depth.</p> + as strings. <c><anno>Column</anno></c> is the starting column (1), + <c><anno>LineLength</anno></c> the maximum line length (80), and + <c><anno>Depth</anno></c> (-1) the maximum print depth.</p> </desc> </func> <func> - <name>fwrite(Format, Data) -></name> - <name>format(Format, Data) -> chars() | UnicodeList</name> + <name name="fwrite" arity="2"/> + <name name="format" arity="2"/> <fsummary>Write formatted output</fsummary> - <type> - <v>Format = atom() | string() | binary()</v> - <v>Data = [term()]</v> - <v>UnicodeList = [Unicode]</v> - <v>Unicode = int() representing valid unicode codepoint</v> - </type> <desc> - <p>Returns a character list which represents <c>Data</c> - formatted in accordance with <c>Format</c>. See + <p>Returns a character list which represents <c><anno>Data</anno></c> + formatted in accordance with <c><anno>Format</anno></c>. See <seealso marker="io#fwrite/1">io:fwrite/1,2,3</seealso> for a detailed description of the available formatting options. A fault is generated if there is an error in the format string or @@ -119,42 +113,32 @@ chars() = [char() | chars()]</code> </desc> </func> <func> - <name>fread(Format, String) -> Result</name> + <name name="fread" arity="2"/> <fsummary>Read formatted input</fsummary> - <type> - <v>Format = String = string()</v> - <v>Result = {ok, InputList, LeftOverChars} | {more, RestFormat, Nchars, InputStack} | {error, What}</v> - <v> InputList = chars()</v> - <v> LeftOverChars = string()</v> - <v> RestFormat = string()</v> - <v> Nchars = int()</v> - <v> InputStack = chars()</v> - <v> What = term()</v> - </type> <desc> - <p>Tries to read <c>String</c> in accordance with the control - sequences in <c>Format</c>. See + <p>Tries to read <c><anno>String</anno></c> in accordance with the control + sequences in <c><anno>Format</anno></c>. See <seealso marker="io#fread/3">io:fread/3</seealso> for a detailed description of the available formatting options. It is - assumed that <c>String</c> contains whole lines. It returns:</p> + assumed that <c><anno>String</anno></c> contains whole lines. It returns:</p> <taglist> - <tag><c>{ok, InputList, LeftOverChars}</c></tag> + <tag><c>{ok, <anno>InputList</anno>, <anno>LeftOverChars</anno>}</c></tag> <item> - <p>The string was read. <c>InputList</c> is the list of + <p>The string was read. <c><anno>InputList</anno></c> is the list of successfully matched and read items, and - <c>LeftOverChars</c> are the input characters not used.</p> + <c><anno>LeftOverChars</anno></c> are the input characters not used.</p> </item> - <tag><c>{more, RestFormat, Nchars, InputStack}</c></tag> + <tag><c>{more, <anno>RestFormat</anno>, <anno>Nchars</anno>, <anno>InputStack</anno>}</c></tag> <item> <p>The string was read, but more input is needed in order - to complete the original format string. <c>RestFormat</c> - is the remaining format string, <c>NChars</c> the number - of characters scanned, and <c>InputStack</c> is the + to complete the original format string. <c><anno>RestFormat</anno></c> + is the remaining format string, <c><anno>Nchars</anno></c> the number + of characters scanned, and <c><anno>InputStack</anno></c> is the reversed list of inputs matched up to that point.</p> </item> - <tag><c>{error, What}</c></tag> + <tag><c>{error, <anno>What</anno>}</c></tag> <item> - <p>The read operation failed and the parameter <c>What</c> + <p>The read operation failed and the parameter <c><anno>What</anno></c> gives a hint about the error.</p> </item> </taglist> @@ -165,17 +149,8 @@ chars() = [char() | chars()]</code> </desc> </func> <func> - <name>fread(Continuation, String, Format) -> Return</name> + <name name="fread" arity="3"/> <fsummary>Re-entrant formatted reader</fsummary> - <type> - <v>Continuation = see below</v> - <v>String = Format = string()</v> - <v>Return = {done, Result, LeftOverChars} | {more, Continuation}</v> - <v> Result = {ok, InputList} | eof | {error, What}</v> - <v> InputList = chars()</v> - <v> What = term()()</v> - <v> LeftOverChars = string()</v> - </type> <desc> <p>This is the re-entrant formatted reader. The continuation of the first call to the functions must be <c>[]</c>. Refer to @@ -184,114 +159,92 @@ chars() = [char() | chars()]</code> re-entrant input scheme works.</p> <p>The function returns:</p> <taglist> - <tag><c>{done, Result, LeftOverChars}</c></tag> + <tag><c>{done, <anno>Result</anno>, <anno>LeftOverChars</anno>}</c></tag> <item> <p>The input is complete. The result is one of the following:</p> <taglist> - <tag><c>{ok, InputList}</c></tag> + <tag><c>{ok, <anno>InputList</anno>}</c></tag> <item> - <p>The string was read. <c>InputList</c> is the list of + <p>The string was read. <c><anno>InputList</anno></c> is the list of successfully matched and read items, and - <c>LeftOverChars</c> are the remaining characters.</p> + <c><anno>LeftOverChars</anno></c> are the remaining characters.</p> </item> <tag><c>eof</c></tag> <item> <p>End of file has been encountered. - <c>LeftOverChars</c> are the input characters not + <c><anno>LeftOverChars</anno></c> are the input characters not used.</p> </item> - <tag><c>{error, What}</c></tag> + <tag><c>{error, <anno>What</anno>}</c></tag> <item> - <p>An error occurred and the parameter <c>What</c> gives + <p>An error occurred and the parameter <c><anno>What</anno></c> gives a hint about the error.</p> </item> </taglist> </item> - <tag><c>{more, Continuation}</c></tag> + <tag><c>{more, <anno>Continuation</anno>}</c></tag> <item> <p>More data is required to build a term. - <c>Continuation</c> must be passed to <c>fread/3</c>, + <c><anno>Continuation</anno></c> must be passed to <c>fread/3</c>, when more data becomes available.</p> </item> </taglist> </desc> </func> <func> - <name>write_atom(Atom) -> chars()</name> + <name name="write_atom" arity="1"/> <fsummary>Write an atom</fsummary> - <type> - <v>Atom = atom()</v> - </type> <desc> <p>Returns the list of characters needed to print the atom - <c>Atom</c>.</p> + <c><anno>Atom</anno></c>.</p> </desc> </func> <func> - <name>write_string(String) -> chars()</name> + <name name="write_string" arity="1"/> <fsummary>Write a string</fsummary> - <type> - <v>String = string()</v> - </type> <desc> - <p>Returns the list of characters needed to print <c>String</c> + <p>Returns the list of characters needed to print <c><anno>String</anno></c> as a string.</p> </desc> </func> <func> - <name>write_char(Integer) -> chars()</name> + <name name="write_char" arity="1"/> <fsummary>Write a character</fsummary> - <type> - <v>Integer = int()</v> - </type> <desc> <p>Returns the list of characters needed to print a character constant in the ISO-latin-1 character set.</p> </desc> </func> <func> - <name>indentation(String, StartIndent) -> int()</name> + <name name="indentation" arity="2"/> <fsummary>Indentation after printing string</fsummary> - <type> - <v>String = string()</v> - <v>StartIndent = int()</v> - </type> <desc> - <p>Returns the indentation if <c>String</c> has been printed, - starting at <c>StartIndent</c>.</p> + <p>Returns the indentation if <c><anno>String</anno></c> has been printed, + starting at <c><anno>StartIndent</anno></c>.</p> </desc> </func> <func> - <name>char_list(Term) -> bool()</name> + <name name="char_list" arity="1"/> <fsummary>Test for a list of characters</fsummary> - <type> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Term</c> is a flat list of + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of characters in the ISO-latin-1 range, otherwise it returns <c>false</c>.</p> </desc> </func> <func> - <name>deep_char_list(Term) -> bool()</name> + <name name="deep_char_list" arity="1"/> <fsummary>Test for a deep list of characters</fsummary> - <type> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Term</c> is a, possibly deep, list + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a, possibly deep, list of characters in the ISO-latin-1 range, otherwise it returns <c>false</c>.</p> </desc> </func> <func> - <name>printable_list(Term) -> bool()</name> + <name name="printable_list" arity="1"/> <fsummary>Test for a list of printable ISO-latin-1 characters</fsummary> - <type> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Term</c> is a flat list of + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of printable ISO-latin-1 characters, otherwise it returns <c>false</c>.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/lib.xml b/lib/stdlib/doc/src/lib.xml index 046add48e8..19fb827cbf 100644 --- a/lib/stdlib/doc/src/lib.xml +++ b/lib/stdlib/doc/src/lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -37,27 +37,23 @@ </description> <funcs> <func> - <name>flush_receive() -> void()</name> + <name name="flush_receive" arity="0"/> <fsummary>Flush messages</fsummary> <desc> <p>Flushes the message buffer of the current process.</p> </desc> </func> <func> - <name>error_message(Format, Args) -> ok</name> + <name name="error_message" arity="2"/> <fsummary>Print error message</fsummary> - <type> - <v>Format = atom() | string() | binary()</v> - <v>Args = [term()]</v> - </type> <desc> - <p>Prints error message <c>Args</c> in accordance with - <c>Format</c>. Similar to <c>io:format/2</c>, see + <p>Prints error message <c><anno>Args</anno></c> in accordance with + <c><anno>Format</anno></c>. Similar to <c>io:format/2</c>, see <seealso marker="io#fwrite/1">io(3)</seealso>.</p> </desc> </func> <func> - <name>progname() -> atom()</name> + <name name="progname" arity="0"/> <fsummary>Return name of Erlang start script</fsummary> <desc> <p>Returns the name of the script that started the current @@ -65,37 +61,24 @@ </desc> </func> <func> - <name>nonl(String1) -> String2</name> + <name name="nonl" arity="1"/> <fsummary>Remove last newline</fsummary> - <type> - <v>String1 = String2 = string()</v> - </type> <desc> <p>Removes the last newline character, if any, in - <c>String1</c>.</p> + <c><anno>String1</anno></c>.</p> </desc> </func> <func> - <name>send(To, Msg)</name> + <name name="send" arity="2"/> <fsummary>Send a message</fsummary> - <type> - <v>To = pid() | Name | {Name,Node}</v> - <v> Name = Node = atom()</v> - <v>Msg = term()</v> - </type> <desc> <p>This function to makes it possible to send a message using the <c>apply/3</c> BIF.</p> </desc> </func> <func> - <name>sendw(To, Msg)</name> + <name name="sendw" arity="2"/> <fsummary>Send a message and wait for an answer</fsummary> - <type> - <v>To = pid() | Name | {Name,Node}</v> - <v> Name = Node = atom()</v> - <v>Msg = term()</v> - </type> <desc> <p>As <c>send/2</c>, but waits for an answer. It is implemented as follows:</p> diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index 92c4eb4f4c..7042c84437 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -60,58 +60,41 @@ </description> <funcs> <func> - <name>all(Pred, List) -> bool()</name> + <name name="all" arity="2"/> <fsummary>Return true if all elements in the list satisfy<c>Pred</c></fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Pred(Elem)</c> returns - <c>true</c> for all elements <c>Elem</c> in <c>List</c>, + <p>Returns <c>true</c> if <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns + <c>true</c> for all elements <c><anno>Elem</anno></c> in <c><anno>List</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>any(Pred, List) -> bool()</name> + <name name="any" arity="2"/> <fsummary>Return true if any of the elements in the list satisfies<c>Pred</c></fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Pred(Elem)</c> returns - <c>true</c> for at least one element <c>Elem</c> in - <c>List</c>.</p> + <p>Returns <c>true</c> if <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns + <c>true</c> for at least one element <c><anno>Elem</anno></c> in + <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>append(ListOfLists) -> List1</name> + <name name="append" arity="1"/> <fsummary>Append a list of lists</fsummary> - <type> - <v>ListOfLists = [List]</v> - <v>List = List1 = [term()]</v> - </type> <desc> <p>Returns a list in which all the sub-lists of - <c>ListOfLists</c> have been appended. For example:</p> + <c><anno>ListOfLists</anno></c> have been appended. For example:</p> <pre> > <input>lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).</input> [1,2,3,a,b,4,5,6]</pre> </desc> </func> <func> - <name>append(List1, List2) -> List3</name> + <name name="append" arity="2"/> <fsummary>Append two lists</fsummary> - <type> - <v>List1 = List2 = List3 = [term()]</v> - </type> <desc> - <p>Returns a new list <c>List3</c> which is made from - the elements of <c>List1</c> followed by the elements of - <c>List2</c>. For example:</p> + <p>Returns a new list <c><anno>List3</anno></c> which is made from + the elements of <c><anno>List1</anno></c> followed by the elements of + <c><anno>List2</anno></c>. For example:</p> <pre> > <input>lists:append("abc", "def").</input> "abcdef"</pre> @@ -119,15 +102,11 @@ </desc> </func> <func> - <name>concat(Things) -> string()</name> + <name name="concat" arity="1"/> <fsummary>Concatenate a list of atoms</fsummary> - <type> - <v>Things = [Thing]</v> - <v> Thing = atom() | integer() | float() | string()</v> - </type> <desc> <p>Concatenates the text representation of the elements - of <c>Things</c>. The elements of <c>Things</c> can be atoms, + of <c><anno>Things</anno></c>. The elements of <c><anno>Things</anno></c> can be atoms, integers, floats or strings.</p> <pre> > <input>lists:concat([doc, '/', file, '.', 3]).</input> @@ -135,87 +114,59 @@ </desc> </func> <func> - <name>delete(Elem, List1) -> List2</name> + <name name="delete" arity="2"/> <fsummary>Delete an element from a list</fsummary> - <type> - <v>Elem = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p>Returns a copy of <c>List1</c> where the first element - matching <c>Elem</c> is deleted, if there is such an + <p>Returns a copy of <c><anno>List1</anno></c> where the first element + matching <c><anno>Elem</anno></c> is deleted, if there is such an element.</p> </desc> </func> <func> - <name>dropwhile(Pred, List1) -> List2</name> + <name name="dropwhile" arity="2"/> <fsummary>Drop elements from a list while a predicate is true</fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p>Drops elements <c>Elem</c> from <c>List1</c> while - <c>Pred(Elem)</c> returns <c>true</c> and returns + <p>Drops elements <c><anno>Elem</anno></c> from <c><anno>List1</anno></c> while + <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c> and returns the remaining list.</p> </desc> </func> <func> - <name>duplicate(N, Elem) -> List</name> + <name name="duplicate" arity="2"/> <fsummary>Make N copies of element</fsummary> - <type> - <v>N = int()</v> - <v>Elem = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns a list which contains N copies of the term - <c>Elem</c>. For example:</p> + <p>Returns a list which contains <c><anno>N</anno></c> copies of the term + <c><anno>Elem</anno></c>. For example:</p> <pre> > <input>lists:duplicate(5, xx).</input> [xx,xx,xx,xx,xx]</pre> </desc> </func> <func> - <name>filter(Pred, List1) -> List2</name> + <name name="filter" arity="2"/> <fsummary>Choose elements which satisfy a predicate</fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p><c>List2</c> is a list of all elements <c>Elem</c> in - <c>List1</c> for which <c>Pred(Elem)</c> returns + <p><c><anno>List2</anno></c> is a list of all elements <c><anno>Elem</anno></c> in + <c><anno>List1</anno></c> for which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c>.</p> </desc> </func> <func> - <name>flatlength(DeepList) -> int()</name> + <name name="flatlength" arity="1"/> <fsummary>Length of flattened deep list</fsummary> - <type> - <v>DeepList = [term() | DeepList]</v> - </type> <desc> - <p>Equivalent to <c>length(flatten(DeepList))</c>, but more + <p>Equivalent to <c>length(flatten(<anno>DeepList</anno>))</c>, but more efficient.</p> </desc> </func> <func> - <name>flatmap(Fun, List1) -> List2</name> + <name name="flatmap" arity="2"/> <fsummary>Map and flatten in one pass</fsummary> - <type> - <v>Fun = fun(A) -> [B]</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v> A = B = term()</v> - </type> <desc> - <p>Takes a function from <c>A</c>s to lists of <c>B</c>s, and a - list of <c>A</c>s (<c>List1</c>) and produces a list of - <c>B</c>s by applying the function to every element in - <c>List1</c> and appending the resulting lists.</p> + <p>Takes a function from <c><anno>A</anno></c>s to lists of <c><anno>B</anno></c>s, and a + list of <c><anno>A</anno></c>s (<c><anno>List1</anno></c>) and produces a list of + <c><anno>B</anno></c>s by applying the function to every element in + <c><anno>List1</anno></c> and appending the resulting lists.</p> <p>That is, <c>flatmap</c> behaves as if it had been defined as follows:</p> <code type="none"> @@ -228,43 +179,29 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>flatten(DeepList) -> List</name> + <name name="flatten" arity="1"/> <fsummary>Flatten a deep list</fsummary> - <type> - <v>DeepList = [term() | DeepList]</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns a flattened version of <c>DeepList</c>.</p> + <p>Returns a flattened version of <c><anno>DeepList</anno></c>.</p> </desc> </func> <func> - <name>flatten(DeepList, Tail) -> List</name> + <name name="flatten" arity="2"/> <fsummary>Flatten a deep list</fsummary> - <type> - <v>DeepList = [term() | DeepList]</v> - <v>Tail = List = [term()]</v> - </type> <desc> - <p>Returns a flattened version of <c>DeepList</c> with the tail - <c>Tail</c> appended.</p> + <p>Returns a flattened version of <c><anno>DeepList</anno></c> with the tail + <c><anno>Tail</anno></c> appended.</p> </desc> </func> <func> - <name>foldl(Fun, Acc0, List) -> Acc1</name> + <name name="foldl" arity="3"/> <fsummary>Fold a function over a list</fsummary> - <type> - <v>Fun = fun(Elem, AccIn) -> AccOut</v> - <v> Elem = term()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Calls <c>Fun(Elem, AccIn)</c> on successive elements <c>A</c> - of <c>List</c>, starting with <c>AccIn == Acc0</c>. - <c>Fun/2</c> must return a new accumulator which is passed to + <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>, <anno>AccIn</anno>)</c> on successive elements <c>A</c> + of <c><anno>List</anno></c>, starting with <c><anno>AccIn</anno> == <anno>Acc0</anno></c>. + <c><anno>Fun</anno>/2</c> must return a new accumulator which is passed to the next call. The function returns the final value of - the accumulator. <c>Acc0</c> is returned if the list is empty. + the accumulator. <c><anno>Acc0</anno></c> is returned if the list is empty. For example:</p> <pre> > <input>lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).</input> @@ -274,14 +211,8 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>foldr(Fun, Acc0, List) -> Acc1</name> + <name name="foldr" arity="3"/> <fsummary>Fold a function over a list</fsummary> - <type> - <v>Fun = fun(Elem, AccIn) -> AccOut</v> - <v> Elem = term()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Like <c>foldl/3</c>, but the list is traversed from right to left. For example:</p> @@ -297,33 +228,23 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>foreach(Fun, List) -> void()</name> + <name name="foreach" arity="2"/> <fsummary>Apply a function to each element of a list</fsummary> - <type> - <v>Fun = fun(Elem) -> void()</v> - <v> Elem = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Calls <c>Fun(Elem)</c> for each element <c>Elem</c> in - <c>List</c>. This function is used for its side effects and + <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> for each element <c><anno>Elem</anno></c> in + <c><anno>List</anno></c>. This function is used for its side effects and the evaluation order is defined to be the same as the order of the elements in the list.</p> </desc> </func> <func> - <name>keydelete(Key, N, TupleList1) -> TupleList2</name> + <name name="keydelete" arity="3"/> <fsummary>Delete an element from a list of tuples</fsummary> - <type> - <v>Key = term()</v> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v> Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> - <p>Returns a copy of <c>TupleList1</c> where the first - occurrence of a tuple whose <c>N</c>th element compares equal to - <c>Key</c> is deleted, if there is such a tuple.</p> + <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first + occurrence of a tuple whose <c><anno>N</anno></c>th element compares equal to + <c><anno>Key</anno></c> is deleted, if there is such a tuple.</p> </desc> </func> <func> @@ -343,19 +264,14 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>keymap(Fun, N, TupleList1) -> TupleList2</name> + <name name="keymap" arity="3"/> <fsummary>Map a function over a list of tuples</fsummary> - <type> - <v>Fun = fun(Term1) -> Term2</v> - <v> Term1 = Term2 = term()</v> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [tuple()]</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Returns a list of tuples where, for each tuple in - <c>TupleList1</c>, the <c>N</c>th element <c>Term1</c> of the tuple + <c><anno>TupleList1</anno></c>, the <c><anno>N</anno></c>th element <c><anno>Term1</anno></c> of the tuple has been replaced with the result of calling - <c>Fun(Term1)</c>.</p> + <c><anno>Fun</anno>(<anno>Term1</anno>)</c>.</p> <p>Examples:</p> <pre> > <input>Fun = fun(Atom) -> atom_to_list(Atom) end.</input> @@ -365,7 +281,7 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>keymember(Key, N, TupleList) -> bool()</name> + <name>keymember(Key, N, TupleList) -> boolean()</name> <fsummary>Test for membership of a list of tuples</fsummary> <type> <v>Key = term()</v> @@ -380,37 +296,28 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>keymerge(N, TupleList1, TupleList2) -> TupleList3</name> + <name name="keymerge" arity="3"/> <fsummary>Merge two key-sorted lists of tuples</fsummary> - <type> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = TupleList3 = [Tuple]</v> - <v> Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> - <p>Returns the sorted list formed by merging <c>TupleList1</c> - and <c>TupleList2</c>. The merge is performed on - the <c>N</c>th element of each tuple. Both <c>TupleList1</c> and - <c>TupleList2</c> must be key-sorted prior to evaluating this + <p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c> + and <c><anno>TupleList2</anno></c>. The merge is performed on + the <c><anno>N</anno></c>th element of each tuple. Both <c><anno>TupleList1</anno></c> and + <c><anno>TupleList2</anno></c> must be key-sorted prior to evaluating this function. When two tuples compare equal, the tuple from - <c>TupleList1</c> is picked before the tuple from - <c>TupleList2</c>.</p> + <c><anno>TupleList1</anno></c> is picked before the tuple from + <c><anno>TupleList2</anno></c>.</p> </desc> </func> <func> - <name>keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2</name> + <name name="keyreplace" arity="4"/> <fsummary>Replace an element in a list of tuples</fsummary> - <type> - <v>Key = term()</v> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v>NewTuple = Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> - <p>Returns a copy of <c>TupleList1</c> where the first - occurrence of a <c>T</c> tuple whose <c>N</c>th element - compares equal to <c>Key</c> is replaced with - <c>NewTuple</c>, if there is such a tuple <c>T</c>.</p> + <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first + occurrence of a <c>T</c> tuple whose <c><anno>N</anno></c>th element + compares equal to <c><anno>Key</anno></c> is replaced with + <c><anno>NewTuple</anno></c>, if there is such a tuple <c>T</c>.</p> </desc> </func> <func> @@ -433,95 +340,63 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>keysort(N, TupleList1) -> TupleList2</name> + <name name="keysort" arity="2"/> <fsummary>Sort a list of tuples</fsummary> - <type> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v> Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Returns a list containing the sorted elements of the list - <c>TupleList1</c>. Sorting is performed on the <c>N</c>th + <c><anno>TupleList1</anno></c>. Sorting is performed on the <c><anno>N</anno></c>th element of the tuples. The sort is stable.</p> </desc> </func> <func> - <name>keystore(Key, N, TupleList1, NewTuple) -> TupleList2</name> + <name name="keystore" arity="4"/> <fsummary>Store an element in a list of tuples</fsummary> - <type> - <v>Key = term()</v> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v>NewTuple = Tuple = tuple()</v> - </type> - <desc> - <p>Returns a copy of <c>TupleList1</c> where the first - occurrence of a tuple <c>T</c> whose <c>N</c>th element - compares equal to <c>Key</c> is replaced with - <c>NewTuple</c>, if there is such a tuple <c>T</c>. If there - is no such tuple <c>T</c> a copy of <c>TupleList1</c> where - [<c>NewTuple</c>] has been appended to the end is + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> + <desc> + <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first + occurrence of a tuple <c>T</c> whose <c><anno>N</anno></c>th element + compares equal to <c><anno>Key</anno></c> is replaced with + <c><anno>NewTuple</anno></c>, if there is such a tuple <c>T</c>. If there + is no such tuple <c>T</c> a copy of <c><anno>TupleList1</anno></c> where + [<c><anno>NewTuple</anno></c>] has been appended to the end is returned.</p> </desc> </func> <func> - <name>keytake(Key, N, TupleList1) -> {value, Tuple, TupleList2} - | false</name> + <name name="keytake" arity="3"/> <fsummary>Extract an element from a list of tuples</fsummary> - <type> - <v>Key = term()</v> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v>Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> - <p>Searches the list of tuples <c>TupleList1</c> for a tuple - whose <c>N</c>th element compares equal to <c>Key</c>. - Returns <c>{value, Tuple, TupleList2}</c> if such a tuple is - found, otherwise <c>false</c>. <c>TupleList2</c> is a copy - of <c>TupleList1</c> where the first occurrence of - <c>Tuple</c> has been removed.</p> + <p>Searches the list of tuples <c><anno>TupleList1</anno></c> for a tuple + whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>. + Returns <c>{value, <anno>Tuple</anno>, <anno>TupleList2</anno>}</c> if such a tuple is + found, otherwise <c>false</c>. <c><anno>TupleList2</anno></c> is a copy + of <c><anno>TupleList1</anno></c> where the first occurrence of + <c><anno>Tuple</anno></c> has been removed.</p> </desc> </func> <func> - <name>last(List) -> Last</name> + <name name="last" arity="1"/> <fsummary>Return last element in a list</fsummary> - <type> - <v>List = [term()], length(List) > 0</v> - <v>Last = term()</v> - </type> <desc> - <p>Returns the last element in <c>List</c>.</p> + <p>Returns the last element in <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>map(Fun, List1) -> List2</name> + <name name="map" arity="2"/> <fsummary>Map a function over a list</fsummary> - <type> - <v>Fun = fun(A) -> B</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v> A = B = term()</v> - </type> <desc> - <p>Takes a function from <c>A</c>s to <c>B</c>s, and a list of - <c>A</c>s and produces a list of <c>B</c>s by applying + <p>Takes a function from <c><anno>A</anno></c>s to <c><anno>B</anno></c>s, and a list of + <c><anno>A</anno></c>s and produces a list of <c><anno>B</anno></c>s by applying the function to every element in the list. This function is used to obtain the return values. The evaluation order is implementation dependent.</p> </desc> </func> <func> - <name>mapfoldl(Fun, Acc0, List1) -> {List2, Acc1}</name> + <name name="mapfoldl" arity="3"/> <fsummary>Map and fold in one pass</fsummary> - <type> - <v>Fun = fun(A, AccIn) -> {B, AccOut}</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v> A = B = term()</v> - </type> <desc> <p><c>mapfoldl</c> combines the operations of <c>map/2</c> and <c>foldl/3</c> into one pass. An example, summing @@ -533,35 +408,24 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>mapfoldr(Fun, Acc0, List1) -> {List2, Acc1}</name> + <name name="mapfoldr" arity="3"/> <fsummary>Map and fold in one pass</fsummary> - <type> - <v>Fun = fun(A, AccIn) -> {B, AccOut}</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v> A = B = term()</v> - </type> <desc> <p><c>mapfoldr</c> combines the operations of <c>map/2</c> and <c>foldr/3</c> into one pass.</p> </desc> </func> <func> - <name>max(List) -> Max</name> + <name name="max" arity="1"/> <fsummary>Return maximum element of a list</fsummary> - <type> - <v>List = [term()], length(List) > 0</v> - <v>Max = term()</v> - </type> <desc> - <p>Returns the first element of <c>List</c> that compares + <p>Returns the first element of <c><anno>List</anno></c> that compares greater than or equal to all other elements of - <c>List</c>.</p> + <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>member(Elem, List) -> bool()</name> + <name>member(Elem, List) -> boolean()</name> <fsummary>Test for membership of a list</fsummary> <type> <v>Elem = term()</v> @@ -573,112 +437,84 @@ flatmap(Fun, List1) -> </desc> </func> <func> - <name>merge(ListOfLists) -> List1</name> + <name name="merge" arity="1"/> <fsummary>Merge a list of sorted lists</fsummary> - <type> - <v>ListOfLists = [List]</v> - <v>List = List1 = [term()]</v> - </type> <desc> <p>Returns the sorted list formed by merging all the sub-lists - of <c>ListOfLists</c>. All sub-lists must be sorted prior to + of <c><anno>ListOfLists</anno></c>. All sub-lists must be sorted prior to evaluating this function. When two elements compare equal, the element from the sub-list with the lowest position in - <c>ListOfLists</c> is picked before the other element.</p> + <c><anno>ListOfLists</anno></c> is picked before the other element.</p> </desc> </func> <func> - <name>merge(List1, List2) -> List3</name> + <name name="merge" arity="2"/> <fsummary>Merge two sorted lists</fsummary> - <type> - <v>List1 = List2 = List3 = [term()]</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c> and - <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and + <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be sorted prior to evaluating this function. When two elements - compare equal, the element from <c>List1</c> is picked - before the element from <c>List2</c>.</p> + compare equal, the element from <c><anno>List1</anno></c> is picked + before the element from <c><anno>List2</anno></c>.</p> </desc> </func> <func> - <name>merge(Fun, List1, List2) -> List3</name> + <name name="merge" arity="3"/> <fsummary>Merge two sorted list</fsummary> - <type> - <v>Fun = fun(A, B) -> bool()</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v>List3 = [A | B]</v> - <v> A = B = term()</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c> and - <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and + <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be sorted according to the <seealso marker="#ordering_function">ordering function</seealso> - <c>Fun</c> prior to evaluating this function. <c>Fun(A, - B)</c> should return <c>true</c> if <c>A</c> compares less - than or equal to <c>B</c> in the ordering, <c>false</c> + <c><anno>Fun</anno></c> prior to evaluating this function. <c><anno>Fun</anno>(<anno>A</anno>, + <anno>B</anno>)</c> should return <c>true</c> if <c><anno>A</anno></c> compares less + than or equal to <c><anno>B</anno></c> in the ordering, <c>false</c> otherwise. When two elements compare equal, the element from - <c>List1</c> is picked before the element from - <c>List2</c>.</p> + <c><anno>List1</anno></c> is picked before the element from + <c><anno>List2</anno></c>.</p> </desc> </func> <func> - <name>merge3(List1, List2, List3) -> List4</name> + <name name="merge3" arity="3"/> <fsummary>Merge three sorted lists</fsummary> - <type> - <v>List1 = List2 = List3 = List4 = [term()]</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c>, - <c>List2</c> and <c>List3</c>. All of <c>List1</c>, - <c>List2</c> and <c>List3</c> must be sorted prior to + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c>, + <c><anno>List2</anno></c> and <c><anno>List3</anno></c>. All of <c><anno>List1</anno></c>, + <c><anno>List2</anno></c> and <c><anno>List3</anno></c> must be sorted prior to evaluating this function. When two elements compare equal, - the element from <c>List1</c>, if there is such an element, + the element from <c><anno>List1</anno></c>, if there is such an element, is picked before the other element, otherwise the element - from <c>List2</c> is picked before the element from - <c>List3</c>.</p> + from <c><anno>List2</anno></c> is picked before the element from + <c><anno>List3</anno></c>.</p> </desc> </func> <func> - <name>min(List) -> Min</name> + <name name="min" arity="1"/> <fsummary>Return minimum element of a list</fsummary> - <type> - <v>List = [term()], length(List) > 0</v> - <v>Min = term()</v> - </type> <desc> - <p>Returns the first element of <c>List</c> that compares + <p>Returns the first element of <c><anno>List</anno></c> that compares less than or equal to all other elements of - <c>List</c>.</p> + <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>nth(N, List) -> Elem</name> + <name name="nth" arity="2"/> <fsummary>Return the Nth element of a list</fsummary> - <type> - <v>N = 1..length(List)</v> - <v>List = [term()]</v> - <v>Elem = term()</v> - </type> + <type_desc variable="N">1..length(<anno>List</anno>)</type_desc> <desc> - <p>Returns the <c>N</c>th element of <c>List</c>. For example:</p> + <p>Returns the <c><anno>N</anno></c>th element of <c><anno>List</anno></c>. For example:</p> <pre> > <input>lists:nth(3, [a, b, c, d, e]).</input> c</pre> </desc> </func> <func> - <name>nthtail(N, List1) -> Tail</name> + <name name="nthtail" arity="2"/> <fsummary>Return the Nth tail of a list</fsummary> - <type> - <v>N = 0..length(List1)</v> - <v>List1 = Tail = [term()]</v> - </type> + <type_desc variable="N">0..length(<anno>List</anno>)</type_desc> <desc> - <p>Returns the <c>N</c>th tail of <c>List</c>, that is, the sublist of - <c>List</c> starting at <c>N+1</c> and continuing up to + <p>Returns the <c><anno>N</anno></c>th tail of <c><anno>List</anno></c>, that is, the sublist of + <c><anno>List</anno></c> starting at <c><anno>N</anno>+1</c> and continuing up to the end of the list. For example:</p> <pre> > <input>lists:nthtail(3, [a, b, c, d, e]).</input> @@ -692,18 +528,13 @@ c</pre> </desc> </func> <func> - <name>partition(Pred, List) -> {Satisfying, NonSatisfying}</name> + <name name="partition" arity="2"/> <fsummary>Partition a list into two lists based on a predicate</fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List = Satisfying = NonSatisfying = [term()]</v> - </type> <desc> - <p>Partitions <c>List</c> into two lists, where the first list - contains all elements for which <c>Pred(Elem)</c> returns + <p>Partitions <c><anno>List</anno></c> into two lists, where the first list + contains all elements for which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c>, and the second list contains all elements for - which <c>Pred(Elem)</c> returns <c>false</c>.</p> + which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>false</c>.</p> <p>Examples:</p> <pre> > <input>lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).</input> @@ -715,24 +546,18 @@ c</pre> </desc> </func> <func> - <name>prefix(List1, List2) -> bool()</name> + <name name="prefix" arity="2"/> <fsummary>Test for list prefix</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p>Returns <c>true</c> if <c>List1</c> is a prefix of - <c>List2</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>List1</anno></c> is a prefix of + <c><anno>List2</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>reverse(List1) -> List2</name> + <name name="reverse" arity="1"/> <fsummary>Reverse a list</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p>Returns a list with the top level elements in <c>List1</c> + <p>Returns a list with the elements in <c><anno>List1</anno></c> in reverse order.</p> </desc> </func> @@ -743,7 +568,7 @@ c</pre> <v>List1 = Tail = List2 = [term()]</v> </type> <desc> - <p>Returns a list with the top level elements in <c>List1</c> + <p>Returns a list with the elements in <c>List1</c> in reverse order, with the tail <c>Tail</c> appended. For example:</p> <pre> @@ -752,22 +577,18 @@ c</pre> </desc> </func> <func> - <name>seq(From, To) -> Seq</name> - <name>seq(From, To, Incr) -> Seq</name> + <name name="seq" arity="2"/> + <name name="seq" arity="3"/> <fsummary>Generate a sequence of integers</fsummary> - <type> - <v>From = To = Incr = int()</v> - <v>Seq = [int()]</v> - </type> <desc> - <p>Returns a sequence of integers which starts with <c>From</c> - and contains the successive results of adding <c>Incr</c> to - the previous element, until <c>To</c> has been reached or - passed (in the latter case, <c>To</c> is not an element of - the sequence). <c>Incr</c> defaults to 1.</p> - <p>Failure: If <c><![CDATA[To<From-Incr]]></c> and <c>Incr</c> - is positive, or if <c>To>From-Incr</c> and <c>Incr</c> is - negative, or if <c>Incr==0</c> and <c>From/=To</c>.</p> + <p>Returns a sequence of integers which starts with <c><anno>From</anno></c> + and contains the successive results of adding <c><anno>Incr</anno></c> to + the previous element, until <c><anno>To</anno></c> has been reached or + passed (in the latter case, <c><anno>To</anno></c> is not an element of + the sequence). <c><anno>Incr</anno></c> defaults to 1.</p> + <p>Failure: If <c><anno>To</anno><<anno>From</anno>-<anno>Incr</anno></c> and <c><anno>Incr</anno></c> + is positive, or if <c><anno>To</anno>><anno>From</anno>-<anno>Incr</anno></c> and <c><anno>Incr</anno></c> is + negative, or if <c><anno>Incr</anno>==0</c> and <c><anno>From</anno>/=<anno>To</anno></c>.</p> <p>The following equalities hold for all sequences:</p> <code type="none"> length(lists:seq(From, To)) == To-From+1 @@ -787,57 +608,41 @@ length(lists:seq(From, To, Incr)) == (To-From+Incr) div Incr</code> </desc> </func> <func> - <name>sort(List1) -> List2</name> + <name name="sort" arity="1"/> <fsummary>Sort a list</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - </type> <desc> <p>Returns a list containing the sorted elements of - <c>List1</c>.</p> + <c><anno>List1</anno></c>.</p> </desc> </func> <func> - <name>sort(Fun, List1) -> List2</name> + <name name="sort" arity="2"/> <fsummary>Sort a list</fsummary> - <type> - <v>Fun = fun(Elem1, Elem2) -> bool()</v> - <v> Elem1 = Elem2 = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> <p>Returns a list containing the sorted elements of - <c>List1</c>, according to the <seealso + <c><anno>List1</anno></c>, according to the <seealso marker="#ordering_function">ordering function</seealso> - <c>Fun</c>. <c>Fun(A, B)</c> should return <c>true</c> if - <c>A</c> compares less than or equal to <c>B</c> in the + <c><anno>Fun</anno></c>. <c><anno>Fun</anno>(<anno>A</anno>, <anno>B</anno>)</c> should return <c>true</c> if + <c><anno>A</anno></c> compares less than or equal to <c><anno>B</anno></c> in the ordering, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>split(N, List1) -> {List2, List3}</name> + <name name="split" arity="2"/> <fsummary>Split a list into two lists</fsummary> - <type> - <v>N = 0..length(List1)</v> - <v>List1 = List2 = List3 = [term()]</v> - </type> + <type_desc variable="N">0..length(<anno>List1</anno>)</type_desc> <desc> - <p>Splits <c>List1</c> into <c>List2</c> and <c>List3</c>. - <c>List2</c> contains the first <c>N</c> elements and - <c>List3</c> the rest of the elements (the <c>N</c>th tail).</p> + <p>Splits <c><anno>List1</anno></c> into <c><anno>List2</anno></c> and <c><anno>List3</anno></c>. + <c><anno>List2</anno></c> contains the first <c><anno>N</anno></c> elements and + <c><anno>List3</anno></c> the rest of the elements (the <c><anno>N</anno></c>th tail).</p> </desc> </func> <func> - <name>splitwith(Pred, List) -> {List1, List2}</name> + <name name="splitwith" arity="2"/> <fsummary>Split a list into two lists based on a predicate</fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List = List1 = List2 = [term()]</v> - </type> <desc> - <p>Partitions <c>List</c> into two lists according to - <c>Pred</c>. <c>splitwith/2</c> behaves as if it is defined + <p>Partitions <c><anno>List</anno></c> into two lists according to + <c><anno>Pred</anno></c>. <c>splitwith/2</c> behaves as if it is defined as follows:</p> <code type="none"> splitwith(Pred, List) -> @@ -853,31 +658,23 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>sublist(List1, Len) -> List2</name> + <name name="sublist" arity="2"/> <fsummary>Return a sub-list of a certain length, starting at the first position</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - <v>Len = int()</v> - </type> <desc> - <p>Returns the sub-list of <c>List1</c> starting at position 1 - and with (max) <c>Len</c> elements. It is not an error for - <c>Len</c> to exceed the length of the list -- in that case + <p>Returns the sub-list of <c><anno>List1</anno></c> starting at position 1 + and with (max) <c><anno>Len</anno></c> elements. It is not an error for + <c><anno>Len</anno></c> to exceed the length of the list -- in that case the whole list is returned.</p> </desc> </func> <func> - <name>sublist(List1, Start, Len) -> List2</name> + <name name="sublist" arity="3"/> <fsummary>Return a sub-list starting at a given position and with a given number of elements</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - <v>Start = 1..(length(List1)+1)</v> - <v>Len = int()</v> - </type> + <type_desc variable="Start">1..(length(<anno>List1</anno>)+1)</type_desc> <desc> - <p>Returns the sub-list of <c>List1</c> starting at <c>Start</c> - and with (max) <c>Len</c> elements. It is not an error for - <c>Start+Len</c> to exceed the length of the list.</p> + <p>Returns the sub-list of <c><anno>List1</anno></c> starting at <c><anno>Start</anno></c> + and with (max) <c><anno>Len</anno></c> elements. It is not an error for + <c><anno>Start</anno>+<anno>Len</anno></c> to exceed the length of the list.</p> <pre> > <input>lists:sublist([1,2,3,4], 2, 2).</input> [2,3] @@ -888,15 +685,12 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>subtract(List1, List2) -> List3</name> + <name name="subtract" arity="2"/> <fsummary>Subtract the element in one list from another list</fsummary> - <type> - <v>List1 = List2 = List3 = [term()]</v> - </type> <desc> - <p>Returns a new list <c>List3</c> which is a copy of - <c>List1</c>, subjected to the following procedure: for each - element in <c>List2</c>, its first occurrence in <c>List1</c> + <p>Returns a new list <c><anno>List3</anno></c> which is a copy of + <c><anno>List1</anno></c>, subjected to the following procedure: for each + element in <c><anno>List2</anno></c>, its first occurrence in <c><anno>List1</anno></c> is deleted. For example:</p> <pre> > <input>lists:subtract("123212", "212").</input> @@ -911,151 +705,112 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>suffix(List1, List2) -> bool()</name> + <name name="suffix" arity="2"/> <fsummary>Test for list suffix</fsummary> <desc> - <p>Returns <c>true</c> if <c>List1</c> is a suffix of - <c>List2</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>List1</anno></c> is a suffix of + <c><anno>List2</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>sum(List) -> number()</name> + <name name="sum" arity="1"/> <fsummary>Return sum of elements in a list</fsummary> - <type> - <v>List = [number()]</v> - </type> <desc> - <p>Returns the sum of the elements in <c>List</c>.</p> + <p>Returns the sum of the elements in <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>takewhile(Pred, List1) -> List2</name> + <name name="takewhile" arity="2"/> <fsummary>Take elements from a list while a predicate is true</fsummary> - <type> - <v>Pred = fun(Elem) -> bool()</v> - <v> Elem = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> - <p>Takes elements <c>Elem</c> from <c>List1</c> while - <c>Pred(Elem)</c> returns <c>true</c>, that is, + <p>Takes elements <c><anno>Elem</anno></c> from <c><anno>List1</anno></c> while + <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c>, that is, the function returns the longest prefix of the list for which all elements satisfy the predicate.</p> </desc> </func> <func> - <name>ukeymerge(N, TupleList1, TupleList2) -> TupleList3</name> + <name name="ukeymerge" arity="3"/> <fsummary>Merge two key-sorted lists of tuples, removing duplicates</fsummary> - <type> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = TupleList3 = [Tuple]</v> - <v> Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> - <p>Returns the sorted list formed by merging <c>TupleList1</c> - and <c>TupleList2</c>. The merge is performed on the - <c>N</c>th element of each tuple. Both <c>TupleList1</c> and - <c>TupleList2</c> must be key-sorted without duplicates + <p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c> + and <c><anno>TupleList2</anno></c>. The merge is performed on the + <c><anno>N</anno></c>th element of each tuple. Both <c><anno>TupleList1</anno></c> and + <c><anno>TupleList2</anno></c> must be key-sorted without duplicates prior to evaluating this function. When two tuples compare - equal, the tuple from <c>TupleList1</c> is picked and the - one from <c>TupleList2</c> deleted.</p> + equal, the tuple from <c><anno>TupleList1</anno></c> is picked and the + one from <c><anno>TupleList2</anno></c> deleted.</p> </desc> </func> <func> - <name>ukeysort(N, TupleList1) -> TupleList2</name> + <name name="ukeysort" arity="2"/> <fsummary>Sort a list of tuples, removing duplicates</fsummary> - <type> - <v>N = 1..tuple_size(Tuple)</v> - <v>TupleList1 = TupleList2 = [Tuple]</v> - <v> Tuple = tuple()</v> - </type> + <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> <desc> <p>Returns a list containing the sorted elements of the list - <c>TupleList1</c> where all but the first tuple of the + <c><anno>TupleList1</anno></c> where all but the first tuple of the tuples comparing equal have been deleted. Sorting is - performed on the <c>N</c>th element of the tuples.</p> + performed on the <c><anno>N</anno></c>th element of the tuples.</p> </desc> </func> <func> - <name>umerge(ListOfLists) -> List1</name> + <name name="umerge" arity="1"/> <fsummary>Merge a list of sorted lists, removing duplicates</fsummary> - <type> - <v>ListOfLists = [List]</v> - <v>List = List1 = [term()]</v> - </type> <desc> <p>Returns the sorted list formed by merging all the sub-lists - of <c>ListOfLists</c>. All sub-lists must be sorted and + of <c><anno>ListOfLists</anno></c>. All sub-lists must be sorted and contain no duplicates prior to evaluating this function. When two elements compare equal, the element from the - sub-list with the lowest position in <c>ListOfLists</c> is + sub-list with the lowest position in <c><anno>ListOfLists</anno></c> is picked and the other one deleted.</p> </desc> </func> <func> - <name>umerge(List1, List2) -> List3</name> + <name name="umerge" arity="2"/> <fsummary>Merge two sorted lists, removing duplicates</fsummary> - <type> - <v>List1 = List2 = List3 = [term()]</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c> and - <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and + <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be sorted and contain no duplicates prior to evaluating this function. When two elements compare equal, the element from - <c>List1</c> is picked and the one from <c>List2</c> + <c><anno>List1</anno></c> is picked and the one from <c><anno>List2</anno></c> deleted.</p> </desc> </func> <func> - <name>umerge(Fun, List1, List2) -> List3</name> + <name name="umerge" arity="3"/> <fsummary>Merge two sorted lists, removing duplicates</fsummary> - <type> - <v>Fun = fun(A, B) -> bool()</v> - <v>List1 = [A]</v> - <v>List2 = [B]</v> - <v>List3 = [A | B]</v> - <v> A = B = term()</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c> and - <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and + <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be sorted according to the <seealso marker="#ordering_function">ordering function</seealso> <c>Fun</c> and contain no duplicates prior to evaluating - this function. <c>Fun(A, B)</c> should return <c>true</c> if - <c>A</c> compares less than or equal to <c>B</c> in the + this function. <c><anno>Fun</anno>(<anno>A</anno>, <anno>B</anno>)</c> should return <c>true</c> if + <c><anno>A</anno></c> compares less than or equal to <c><anno>B</anno></c> in the ordering, <c>false</c> otherwise. When two elements compare equal, the element from - <c>List1</c> is picked and the one from <c>List2</c> + <c><anno>List1</anno></c> is picked and the one from <c><anno>List2</anno></c> deleted.</p> </desc> </func> <func> - <name>umerge3(List1, List2, List3) -> List4</name> + <name name="umerge3" arity="3"/> <fsummary>Merge three sorted lists, removing duplicates</fsummary> - <type> - <v>List1 = List2 = List3 = List4 = [term()]</v> - </type> <desc> - <p>Returns the sorted list formed by merging <c>List1</c>, - <c>List2</c> and <c>List3</c>. All of <c>List1</c>, - <c>List2</c> and <c>List3</c> must be sorted and contain no + <p>Returns the sorted list formed by merging <c><anno>List1</anno></c>, + <c><anno>List2</anno></c> and <c><anno>List3</anno></c>. All of <c><anno>List1</anno></c>, + <c><anno>List2</anno></c> and <c><anno>List3</anno></c> must be sorted and contain no duplicates prior to evaluating this function. When two - elements compare equal, the element from <c>List1</c> is + elements compare equal, the element from <c><anno>List1</anno></c> is picked if there is such an element, otherwise the element - from <c>List2</c> is picked, and the other one deleted.</p> + from <c><anno>List2</anno></c> is picked, and the other one deleted.</p> </desc> </func> <func> - <name>unzip(List1) -> {List2, List3}</name> + <name name="unzip" arity="1"/> <fsummary>Unzip a list of two-tuples into two lists</fsummary> - <type> - <v>List1 = [{X, Y}]</v> - <v>List2 = [X]</v> - <v>List3 = [Y]</v> - <v> X = Y = term()</v> - </type> <desc> <p>"Unzips" a list of two-tuples into two lists, where the first list contains the first element of each tuple, and the second @@ -1063,15 +818,8 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>unzip3(List1) -> {List2, List3, List4}</name> + <name name="unzip3" arity="1"/> <fsummary>Unzip a list of three-tuples into three lists</fsummary> - <type> - <v>List1 = [{X, Y, Z}]</v> - <v>List2 = [X]</v> - <v>List3 = [Y]</v> - <v>List4 = [Z]</v> - <v> X = Y = Z = term()</v> - </type> <desc> <p>"Unzips" a list of three-tuples into three lists, where the first list contains the first element of each tuple, @@ -1080,44 +828,30 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>usort(List1) -> List2</name> + <name name="usort" arity="1"/> <fsummary>Sort a list, removing duplicates</fsummary> - <type> - <v>List1 = List2 = [term()]</v> - </type> <desc> <p>Returns a list containing the sorted elements of - <c>List1</c> where all but the first element of the elements + <c><anno>List1</anno></c> where all but the first element of the elements comparing equal have been deleted.</p> </desc> </func> <func> - <name>usort(Fun, List1) -> List2</name> + <name name="usort" arity="2"/> <fsummary>Sort a list, removing duplicates</fsummary> - <type> - <v>Fun = fun(Elem1, Elem2) -> bool()</v> - <v> Elem1 = Elem2 = term()</v> - <v>List1 = List2 = [term()]</v> - </type> <desc> <p>Returns a list which contains the sorted elements of - <c>List1</c> where all but the first element of the elements + <c><anno>List1</anno></c> where all but the first element of the elements comparing equal according to the <seealso marker="#ordering_function">ordering function</seealso> - <c>Fun</c> have been deleted. <c>Fun(A, B)</c> should return + <c><anno>Fun</anno></c> have been deleted. <c><anno>Fun</anno>(A, B)</c> should return <c>true</c> if <c>A</c> compares less than or equal to <c>B</c> in the ordering, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>zip(List1, List2) -> List3</name> + <name name="zip" arity="2"/> <fsummary>Zip two lists into a list of two-tuples</fsummary> - <type> - <v>List1 = [X]</v> - <v>List2 = [Y]</v> - <v>List3 = [{X, Y}]</v> - <v> X = Y = term()</v> - </type> <desc> <p>"Zips" two lists of equal length into one list of two-tuples, where the first element of each tuple is taken from the first @@ -1126,15 +860,8 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>zip3(List1, List2, List3) -> List4</name> + <name name="zip3" arity="3"/> <fsummary>Zip three lists into a list of three-tuples</fsummary> - <type> - <v>List1 = [X]</v> - <v>List2 = [Y]</v> - <v>List3 = [Z]</v> - <v>List3 = [{X, Y, Z}]</v> - <v> X = Y = Z = term()</v> - </type> <desc> <p>"Zips" three lists of equal length into one list of three-tuples, where the first element of each tuple is taken @@ -1145,20 +872,13 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>zipwith(Combine, List1, List2) -> List3</name> + <name name="zipwith" arity="3"/> <fsummary>Zip two lists into one list according to a fun</fsummary> - <type> - <v>Combine = fun(X, Y) -> T</v> - <v>List1 = [X]</v> - <v>List2 = [Y]</v> - <v>List3 = [T]</v> - <v> X = Y = T = term()</v> - </type> <desc> <p>Combine the elements of two lists of equal length into one - list. For each pair <c>X, Y</c> of list elements from the two + list. For each pair <c><anno>X</anno>, <anno>Y</anno></c> of list elements from the two lists, the element in the result list will be - <c>Combine(X, Y)</c>.</p> + <c><anno>Combine</anno>(<anno>X</anno>, <anno>Y</anno>)</c>.</p> <p><c>zipwith(fun(X, Y) -> {X,Y} end, List1, List2)</c> is equivalent to <c>zip(List1, List2)</c>.</p> <p>Example:</p> @@ -1168,21 +888,13 @@ splitwith(Pred, List) -> </desc> </func> <func> - <name>zipwith3(Combine, List1, List2, List3) -> List4</name> + <name name="zipwith3" arity="4"/> <fsummary>Zip three lists into one list according to a fun</fsummary> - <type> - <v>Combine = fun(X, Y, Z) -> T</v> - <v>List1 = [X]</v> - <v>List2 = [Y]</v> - <v>List3 = [Z]</v> - <v>List4 = [T]</v> - <v> X = Y = Z = T = term()</v> - </type> <desc> <p>Combine the elements of three lists of equal length into one - list. For each triple <c>X, Y, Z</c> of list elements from + list. For each triple <c><anno>X</anno>, <anno>Y</anno>, <anno>Z</anno></c> of list elements from the three lists, the element in the result list will be - <c>Combine(X, Y, Z)</c>.</p> + <c><anno>Combine</anno>(<anno>X</anno>, <anno>Y</anno>, <anno>Z</anno>)</c>.</p> <p><c>zipwith3(fun(X, Y, Z) -> {X,Y,Z} end, List1, List2, List3)</c> is equivalent to <c>zip3(List1, List2, List3)</c>.</p> <p>Examples:</p> <pre> diff --git a/lib/stdlib/doc/src/log_mf_h.xml b/lib/stdlib/doc/src/log_mf_h.xml index f8e11339a7..f2b09b58eb 100644 --- a/lib/stdlib/doc/src/log_mf_h.xml +++ b/lib/stdlib/doc/src/log_mf_h.xml @@ -43,28 +43,27 @@ report files <c>1, 2, ....</c>. </p> </description> + <datatypes> + <datatype> + <name name="args"/> + <desc><p>Term to be sent to <seealso marker="gen_event#add_handler/3"> + gen_event:add_handler/3</seealso>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>init(Dir, MaxBytes, MaxFiles)</name> - <name>init(Dir, MaxBytes, MaxFiles, Pred) -> Args</name> + <name name="init" arity="3"/> + <name name="init" arity="4"/> <fsummary>Initiate the event handler</fsummary> - <type> - <v>Dir = string()</v> - <v>MaxBytes = integer()</v> - <v>MaxFiles = 0 < integer() < 256</v> - <v>Pred = fun(Event) -> boolean()</v> - <v>Event = term()</v> - <v>Args = args()</v> - </type> <desc> <p>Initiates the event handler. This function returns - <c>Args</c>, which should be used in a call to - <c>gen_event:add_handler(EventMgr, log_mf_h, Args)</c>. + <c><anno>Args</anno></c>, which should be used in a call to + <c>gen_event:add_handler(EventMgr, log_mf_h, <anno>Args</anno>)</c>. </p> - <p><c>Dir</c> specifies which directory to use for the log - files. <c>MaxBytes</c> specifies the size of each individual - file. <c>MaxFiles</c> specifies how many files are - used. <c>Pred</c> is a predicate function used to filter the + <p><c><anno>Dir</anno></c> specifies which directory to use for the log + files. <c><anno>MaxBytes</anno></c> specifies the size of each individual + file. <c><anno>MaxFiles</anno></c> specifies how many files are + used. <c><anno>Pred</anno></c> is a predicate function used to filter the events. If no predicate function is specified, all events are logged.</p> </desc> diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml index 02e4d6e495..518457d5d8 100644 --- a/lib/stdlib/doc/src/math.xml +++ b/lib/stdlib/doc/src/math.xml @@ -45,7 +45,7 @@ </description> <funcs> <func> - <name>pi() -> float()</name> + <name name="pi" arity="0"/> <fsummary>A useful number</fsummary> <desc> <p>A useful number.</p> diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml index ba9f89685b..f81f8bda96 100644 --- a/lib/stdlib/doc/src/ms_transform.xml +++ b/lib/stdlib/doc/src/ms_transform.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2002</year><year>2010</year> + <year>2002</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -599,12 +599,9 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code> </description> <funcs> <func> - <name>parse_transform(Forms,_Options) -> Forms</name> + <name name="parse_transform" arity="2"/> <fsummary>Transforms Erlang abstract format containing calls to ets/dbg:fun2ms into literal match specifications.</fsummary> - <type> - <v>Forms = Erlang abstract code format, see the erl_parse module description </v> - <v>_Options = Option list, required but not used</v> - </type> + <type_desc variable="Options">Option list, required but not used.</type_desc> <desc> <p>Implements the actual transformation at compile time. This function is called by the compiler to do the source code @@ -617,29 +614,21 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code> </desc> </func> <func> - <name>transform_from_shell(Dialect,Clauses,BoundEnvironment) -> term()</name> + <name name="transform_from_shell" arity="3"/> <fsummary>Used when transforming fun's created in the shell into match_specifications.</fsummary> - <type> - <v>Dialect = ets | dbg</v> - <v>Clauses = Erlang abstract form for a single fun</v> - <v>BoundEnvironment = [{atom(), term()}, ...], list of variable bindings in the shell environment</v> - </type> + <type_desc variable="BoundEnvironment">List of variable bindings in the shell environment.</type_desc> <desc> <p>Implements the actual transformation when the <c>fun2ms</c> functions are called from the shell. In this case the abstract form is for one single fun (parsed by the Erlang shell), and all imported variables should be in the key-value list passed - as <c>BoundEnvironment</c>. The result is a term, normalized, + as <c><anno>BoundEnvironment</anno></c>. The result is a term, normalized, i.e. not in abstract format.</p> </desc> </func> <func> - <name>format_error(Errcode) -> ErrMessage</name> + <name name="format_error" arity="1"/> <fsummary>Error formatting function as required by the parse_transform interface.</fsummary> - <type> - <v>Errcode = term()</v> - <v>ErrMessage = string()</v> - </type> <desc> <p>Takes an error code returned by one of the other functions in the module and creates a textual description of the diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 8cd499f960..d9c220b996 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2010</year> + <year>2004</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -30,6 +30,349 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 1.17.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + erl_tar:extract failed when executed inside a directory + with some parent directory to which the user has no read + access. This has been corrected.</p> + <p> + Own Id: OTP-9368</p> + </item> + <item> + <p> A bug in <c>erl_scan:set_attribute/3</c> has been + fixed. </p> + <p> + Own Id: OTP-9412</p> + </item> + <item> + <p> The contract of <c>io_lib:fread()</c> has been + corrected. </p> + <p> + Own Id: OTP-9413 Aux Id: seq11873 </p> + </item> + <item> + <p> + A crash in io_lib:fread/2 when end of input data was + encountered while trying to match literal characters, + which should return {more,_,_,_} but instead crashed, has + been corrected. Reported by Klas Johansson.</p> + <p> + A similar peculiarity for io:fread when encountering end + of file before any field data has also been corrected.</p> + <p> + Own Id: OTP-9439</p> + </item> + <item> + <p> The contract of <c>timer:now_diff()</c> has been + corrected. (Thanks to Alex Morarash). </p> + <p> + Own Id: OTP-9450</p> + </item> + <item> + <p> + Fix minor typo in gen_fsm documentation (Thanks to Haitao + Li)</p> + <p> + Own Id: OTP-9456</p> + </item> + <item> + <p>The contracts of <c>zip:zip_list_dir/1</c> and + <c>zip:zip_get/2</c> have been corrected. </p> + <p> + Own Id: OTP-9471 Aux Id: seq11887, OTP-9472 </p> + </item> + <item> + <p> A bug in <c>zip:zip_open()</c> has been fixed. </p> + <p> + Own Id: OTP-9472 Aux Id: seq11887, OTP-9471 </p> + </item> + <item> + <p> + Fix trivial documentation errors(Thanks to Matthias Lang)</p> + <p> + Own Id: OTP-9498</p> + </item> + <item> + <p> + Add a proplist() type</p> + <p> + Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)</p> + <p> + Own Id: OTP-9499</p> + </item> + <item> + <p> + fix supervisors restarting temporary children</p> + <p> + In the current implementation of supervisors, temporary + children should never be restarted. However, when a + temporary child is restarted as part of a one_for_all or + rest_for_one strategy where the failing process is not + the temporary child, the supervisor still tries to + restart it.</p> + <p> + Because the supervisor doesn't keep some of the MFA + information of temporary children, this causes the + supervisor to hit its restart limit and crash.</p> + <p> + This patch fixes the behaviour by inserting a clause in + terminate_children/2-3 (private function) that will omit + temporary children when building a list of killed + processes, to avoid having the supervisor trying to + restart them again.</p> + <p> + Only supervisors in need of restarting children used the + list, so the change should be of no impact for the + functions that called terminate_children/2-3 only to kill + all children.</p> + <p> + The documentation has been modified to make this + behaviour more explicit. (Thanks to Fred Hebert)</p> + <p> + Own Id: OTP-9502</p> + </item> + <item> + <p> + fix broken edoc annotations (Thanks to Richard Carlsson)</p> + <p> + Own Id: OTP-9516</p> + </item> + <item> + <p> XML files have been corrected. </p> + <p> + Own Id: OTP-9550 Aux Id: OTP-9541 </p> + </item> + <item> + <p> + Handle rare race in the crypto key server functionality</p> + <p> + Own Id: OTP-9586</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Types and specifications have been added. </p> + <p> + Own Id: OTP-9356</p> + </item> + <item> + <p> The contracts of the <c>queue</c> module have been + modified. </p> + <p> + Own Id: OTP-9418</p> + </item> + <item> + <p> Contracts in STDLIB and Kernel have been improved and + type errors have been corrected. </p> + <p> + Own Id: OTP-9485</p> + </item> + <item> + <p> + Types for several BIFs have been extended/corrected. Also + the types for types for <c>lists:keyfind/3</c>, + <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c> + have been corrected. The incorrect/incomplete types could + cause false dialyzer warnings.</p> + <p> + Own Id: OTP-9496</p> + </item> + </list> + </section> + +</section> + +<section><title>STDLIB 1.17.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The default value <c>undefined</c> was added to + records field types in such a way that the result was not + always a well-formed type. This bug has been fixed. </p> + <p> + Own Id: OTP-9147</p> + </item> + <item> + <p> + Update index file atomically</p> + <p> + Since the log_mf_h index file might be read by other + processes than the error handler (e.g. by the rb tool), + this file should be updated atomically. This will avoid + hitting the time gap between opening the file in write + mode (and thus emptying the file) and the actual update + with the new contents. To do this, a temporary file is + written, and the file:rename/1 used to replace the real + index file.</p> + <p> + Own Id: OTP-9148</p> + </item> + <item> + <p> + Fixed various typos across the documentation (Thanks to + Tuncer Ayaz)</p> + <p> + Own Id: OTP-9154</p> + </item> + <item> + <p> + Supervisors should not save child-specs for temporary + processes when they terminate as they should not be + restarted. Saving the temporary child spec will result in + that you can not start a new temporary process with the + same child spec as an already terminated temporary + process. Since R14B02 you can not restart a temporary + temporary process as arguments are no longer saved, it + has however always been semantically incorrect to restart + a temporary process. Thanks to Filipe David Manana for + reporting this and suggesting a solution.</p> + <p> + Own Id: OTP-9167 Aux Id: OTP-9064 </p> + </item> + <item> + <p> + Various small documentation fixes (Thanks to Bernard + Duggan)</p> + <p> + Own Id: OTP-9172</p> + </item> + <item> + <p> + Fix format_status bug for unregistered gen_event + processes</p> + <p> + Port the gen_fsm code for format_status to gen_event in + order to prevent a lists:concat([...,pid()]) crash when + calling sys:get_status/1 on an unregistered gen_event + process.</p> + <p> + Refactor format_status header code from gen_* behaviours + to module gen.</p> + <p> + Extend the format_status tests in gen_event_SUITE to + cover format_status bugs with anonymous gen_event + processes. (Thanks To Geoff Cant)</p> + <p> + Own Id: OTP-9218</p> + </item> + <item> + <p> + List of pids changed to 'set' in supervisor for dynamic + temporary children. Accessing the list would not scale + well when adding/deleting many children. (Thanks to + Evgeniy Khramtsov)</p> + <p> + Own Id: OTP-9242</p> + </item> + <item> + <p> + Change pool module to attempt to attach to nodes that are + already running</p> + <p> + The pool module prints out an error message and takes no + further action for nodes that are already running. This + patch changes that behavior so that if the return from + slave:start/3 is {already_running, Node} then an attempt + to attach to the node is still made. This makes sense + because the node has been specified by the user in the + .hosts.erlang file indicating a wish for the node to be + part of the pool and a manual attach can be successfully + made after the pool is started.(Thanks to Kelly + McLaughlin)</p> + <p> + Own Id: OTP-9244</p> + </item> + <item> + <p> + unicode: document 16#FFFE and 16#FFFF (non chars)(Thanks + to Tuncer Ayaz)</p> + <p> + Own Id: OTP-9256</p> + </item> + <item> + <p> + re: remove gratuitous "it " in manpage (Thanks to Tuncer + Ayaz)</p> + <p> + Own Id: OTP-9307</p> + </item> + <item> + <p> A bug in erl_eval(3) has been fixed. </p> + <p> + Own Id: OTP-9322</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add <c>timer:tc/1</c> and remove the catch in <c>tc/2</c> + and <c>tc/3</c>. The time measuring functions will thus + no longer trap exits, errors or throws caused by the + measured function.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9169</p> + </item> + <item> + <p> + Allow supervisor:terminate_child(SupRef,Pid) for + simple_one_for_one supervisors</p> + <p> + supervisor:terminate_child/2 was earlier not allowed if + the supervisor used restart strategy simple_one_for_one. + This is now changed so that children of this type of + supervisors can be terminated by specifying the child's + Pid.</p> + <p> + (Thanks to Vance Shipley.)</p> + <p> + Own Id: OTP-9201</p> + </item> + <item> + <p> Types and specifications have been added. </p> + <p> + Own Id: OTP-9267</p> + </item> + <item> + <p> Erlang types and specifications are used for + documentation. </p> + <p> + Own Id: OTP-9271</p> + </item> + <item> + <p>Allow Dets tablenames to be arbitrary terms.</p> + <p> + Own Id: OTP-9282</p> + </item> + <item> + <p> A specification that could cause problems for + Dialyzer has been fixed. An opaque type in erl_eval has + been turned in to a ordinary type. This is a temporary + fix. </p> + <p> + Own Id: OTP-9333</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 1.17.3</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -2451,7 +2794,7 @@ that is, also when starting a gen_server, gen_fsm etc. </p> <p>This limitation has now been properly documented and the behavior of the <c>gen_fsm</c>, <c>gen_server</c>, and - <c>proc_lib</c><c>start</c> and <c>start_link</c> + <c>proc_lib</c> <c>start</c> and <c>start_link</c> functions when providing this option has been changed from hanging indefinitely to failing with reason <c>badarg</c>.</p> @@ -2568,7 +2911,6 @@ <c>join</c> option that can be used to force QLC to use a particular kind of join in some QLC expression.</p> <p>Several other changes have also been included:</p> - <p></p> <list type="bulleted"> <item> <p>The new <c>tmpdir</c> option of <c>cursor/2</c>, diff --git a/lib/stdlib/doc/src/orddict.xml b/lib/stdlib/doc/src/orddict.xml index 1b8b74534b..319083d35b 100644 --- a/lib/stdlib/doc/src/orddict.xml +++ b/lib/stdlib/doc/src/orddict.xml @@ -46,176 +46,123 @@ (<c>==</c>).</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -ordered_dictionary() - as returned by new/0</code> - </section> + <datatypes> + <datatype> + <name name="orddict"/> + <desc><p>As returned by new/0.</p></desc> + </datatype> + </datatypes> + <funcs> <func> - <name>append(Key, Value, Orddict1) -> Orddict2</name> + <name name="append" arity="3"/> <fsummary>Append a value to keys in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>This function appends a new <c>Value</c> to the current list - of values associated with <c>Key</c>. An exception is - generated if the initial value associated with <c>Key</c> is + <p>This function appends a new <c><anno>Value</anno></c> to the current list + of values associated with <c><anno>Key</anno></c>. An exception is + generated if the initial value associated with <c><anno>Key</anno></c> is not a list of values.</p> </desc> </func> <func> - <name>append_list(Key, ValList, Orddict1) -> Orddict2</name> + <name name="append_list" arity="3"/> <fsummary>Append new values to keys in a dictionary</fsummary> - <type> - <v>ValList = [Value]</v> - <v>Key = Value = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>This function appends a list of values <c>ValList</c> to - the current list of values associated with <c>Key</c>. An + <p>This function appends a list of values <c><anno>ValList</anno></c> to + the current list of values associated with <c><anno>Key</anno></c>. An exception is generated if the initial value associated with - <c>Key</c> is not a list of values.</p> + <c><anno>Key</anno></c> is not a list of values.</p> </desc> </func> <func> - <name>erase(Key, Orddict1) -> Orddict2</name> + <name name="erase" arity="2"/> <fsummary>Erase a key from a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> <p>This function erases all items with a given key from a dictionary.</p> </desc> </func> <func> - <name>fetch(Key, Orddict) -> Value</name> + <name name="fetch" arity="2"/> <fsummary>Look-up values in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> - <p>This function returns the value associated with <c>Key</c> - in the dictionary <c>Orddict</c>. <c>fetch</c> assumes that - the <c>Key</c> is present in the dictionary and an exception - is generated if <c>Key</c> is not in the dictionary.</p> + <p>This function returns the value associated with <c><anno>Key</anno></c> + in the dictionary <c><anno>Orddict</anno></c>. <c>fetch</c> assumes that + the <c><anno>Key</anno></c> is present in the dictionary and an exception + is generated if <c><anno>Key</anno></c> is not in the dictionary.</p> </desc> </func> <func> - <name>fetch_keys(Orddict) -> Keys</name> + <name name="fetch_keys" arity="1"/> <fsummary>Return all keys in a dictionary</fsummary> - <type> - <v>Orddict = ordered_dictionary()</v> - <v>Keys = [term()]</v> - </type> <desc> <p>This function returns a list of all keys in the dictionary.</p> </desc> </func> <func> - <name>filter(Pred, Orddict1) -> Orddict2</name> + <name name="filter" arity="2"/> <fsummary>Choose elements which satisfy a predicate</fsummary> - <type> - <v>Pred = fun(Key, Value) -> bool()</v> - <v> Key = Value = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p><c>Orddict2</c> is a dictionary of all keys and values in - <c>Orddict1</c> for which <c>Pred(Key, Value)</c> is <c>true</c>.</p> + <p><c><anno>Orddict2</anno></c> is a dictionary of all keys and values in + <c><anno>Orddict1</anno></c> for which <c><anno>Pred</anno>(<anno>Key</anno>, <anno>Value</anno>)</c> is <c>true</c>.</p> </desc> </func> <func> - <name>find(Key, Orddict) -> {ok, Value} | error</name> + <name name="find" arity="2"/> <fsummary>Search for a key in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> <p>This function searches for a key in a dictionary. Returns - <c>{ok, Value}</c> where <c>Value</c> is the value associated - with <c>Key</c>, or <c>error</c> if the key is not present in + <c>{ok, <anno>Value</anno>}</c> where <c><anno>Value</anno></c> is the value associated + with <c><anno>Key</anno></c>, or <c>error</c> if the key is not present in the dictionary.</p> </desc> </func> <func> - <name>fold(Fun, Acc0, Orddict) -> Acc1</name> + <name name="fold" arity="3"/> <fsummary>Fold a function over a dictionary</fsummary> - <type> - <v>Fun = fun(Key, Value, AccIn) -> AccOut</v> - <v>Key = Value = term()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> - <p>Calls <c>Fun</c> on successive keys and values of - <c>Orddict</c> together with an extra argument <c>Acc</c> - (short for accumulator). <c>Fun</c> must return a new - accumulator which is passed to the next call. <c>Acc0</c> is + <p>Calls <c><anno>Fun</anno></c> on successive keys and values of + <c><anno>Orddict</anno></c> together with an extra argument <c>Acc</c> + (short for accumulator). <c><anno>Fun</anno></c> must return a new + accumulator which is passed to the next call. <c><anno>Acc0</anno></c> is returned if the list is empty. The evaluation order is undefined.</p> </desc> </func> <func> - <name>from_list(List) -> Orddict</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list of pairs to a dictionary</fsummary> - <type> - <v>List = [{Key, Value}]</v> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> - <p>This function converts the <c>Key</c> - <c>Value</c> list - <c>List</c> to a dictionary.</p> + <p>This function converts the <c><anno>Key</anno></c> - <c><anno>Value</anno></c> list + <c><anno>List</anno></c> to a dictionary.</p> </desc> </func> <func> - <name>is_key(Key, Orddict) -> bool()</name> + <name name="is_key" arity="2"/> <fsummary>Test if a key is in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> - <p>This function tests if <c>Key</c> is contained in - the dictionary <c>Orddict</c>.</p> + <p>This function tests if <c><anno>Key</anno></c> is contained in + the dictionary <c><anno>Orddict</anno></c>.</p> </desc> </func> <func> - <name>map(Fun, Orddict1) -> Orddict2</name> + <name name="map" arity="2"/> <fsummary>Map a function over a dictionary</fsummary> - <type> - <v>Fun = fun(Key, Value1) -> Value2</v> - <v> Key = Value1 = Value2 = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p><c>map</c> calls <c>Func</c> on successive keys and values - of <c>Orddict</c> to return a new value for each key. + <p><c>map</c> calls <c><anno>Fun</anno></c> on successive keys and values + of <c><anno>Orddict1</anno></c> to return a new value for each key. The evaluation order is undefined.</p> </desc> </func> <func> - <name>merge(Fun, Orddict1, Orddict2) -> Orddict3</name> + <name name="merge" arity="3"/> <fsummary>Merge two dictionaries</fsummary> - <type> - <v>Fun = fun(Key, Value1, Value2) -> Value</v> - <v> Key = Value1 = Value2 = Value3 = term()</v> - <v>Orddict1 = Orddict2 = Orddict3 = ordered_dictionary()</v> - </type> <desc> - <p><c>merge</c> merges two dictionaries, <c>Orddict1</c> and - <c>Orddict2</c>, to create a new dictionary. All the <c>Key</c> - - <c>Value</c> pairs from both dictionaries are included in + <p><c>merge</c> merges two dictionaries, <c><anno>Orddict1</anno></c> and + <c><anno>Orddict2</anno></c>, to create a new dictionary. All the <c><anno>Key</anno></c> + - <c><anno>Value</anno></c> pairs from both dictionaries are included in the new dictionary. If a key occurs in both dictionaries then - <c>Fun</c> is called with the key and both values to return a + <c><anno>Fun</anno></c> is called with the key and both values to return a new value. <c>merge</c> could be defined as:</p> <code type="none"> merge(Fun, D1, D2) -> @@ -226,75 +173,52 @@ merge(Fun, D1, D2) -> </desc> </func> <func> - <name>new() -> ordered_dictionary()</name> + <name name="new" arity="0"/> <fsummary>Create a dictionary</fsummary> <desc> <p>This function creates a new dictionary.</p> </desc> </func> <func> - <name>size(Orddict) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of elements in an ordered dictionary</fsummary> - <type> - <v>Orddict = ordered_dictionary()</v> - </type> <desc> - <p>Returns the number of elements in an <c>Orddict</c>.</p> + <p>Returns the number of elements in an <c><anno>Orddict</anno></c>.</p> </desc> </func> <func> - <name>store(Key, Value, Orddict1) -> Orddict2</name> + <name name="store" arity="3"/> <fsummary>Store a value in a dictionary</fsummary> - <type> - <v>Key = Value = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>This function stores a <c>Key</c> - <c>Value</c> pair in a - dictionary. If the <c>Key</c> already exists in <c>Orddict1</c>, - the associated value is replaced by <c>Value</c>.</p> + <p>This function stores a <c><anno>Key</anno></c> - <c><anno>Value</anno></c> pair in a + dictionary. If the <c><anno>Key</anno></c> already exists in <c><anno>Orddict1</anno></c>, + the associated value is replaced by <c><anno>Value</anno></c>.</p> </desc> </func> <func> - <name>to_list(Orddict) -> List</name> + <name name="to_list" arity="1"/> <fsummary>Convert a dictionary to a list of pairs</fsummary> - <type> - <v>Orddict = ordered_dictionary()</v> - <v>List = [{Key, Value}]</v> - </type> <desc> <p>This function converts the dictionary to a list representation.</p> </desc> </func> <func> - <name>update(Key, Fun, Orddict1) -> Orddict2</name> + <name name="update" arity="3"/> <fsummary>Update a value in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Fun = fun(Value1) -> Value2</v> - <v> Value1 = Value2 = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>Update a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on the value to get a new value. An exception is generated if - <c>Key</c> is not present in the dictionary.</p> + <c><anno>Key</anno></c> is not present in the dictionary.</p> </desc> </func> <func> - <name>update(Key, Fun, Initial, Orddict1) -> Orddict2</name> + <name name="update" arity="4"/> <fsummary>Update a value in a dictionary</fsummary> - <type> - <v>Key = Initial = term()</v> - <v>Fun = fun(Value1) -> Value2</v> - <v> Value1 = Value2 = term()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>Update a value in a dictionary by calling <c>Fun</c> on - the value to get a new value. If <c>Key</c> is not present - in the dictionary then <c>Initial</c> will be stored as + <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on + the value to get a new value. If <c><anno>Key</anno></c> is not present + in the dictionary then <c><anno>Initial</anno></c> will be stored as the first value. For example <c>append/3</c> could be defined as:</p> <code type="none"> @@ -303,17 +227,12 @@ append(Key, Val, D) -> </desc> </func> <func> - <name>update_counter(Key, Increment, Orddict1) -> Orddict2</name> + <name name="update_counter" arity="3"/> <fsummary>Increment a value in a dictionary</fsummary> - <type> - <v>Key = term()</v> - <v>Increment = number()</v> - <v>Orddict1 = Orddict2 = ordered_dictionary()</v> - </type> <desc> - <p>Add <c>Increment</c> to the value associated with <c>Key</c> - and store this value. If <c>Key</c> is not present in - the dictionary then <c>Increment</c> will be stored as + <p>Add <c><anno>Increment</anno></c> to the value associated with <c><anno>Key</anno></c> + and store this value. If <c><anno>Key</anno></c> is not present in + the dictionary then <c><anno>Increment</anno></c> will be stored as the first value.</p> <p>This could be defined as:</p> <code type="none"> diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml index a20ab2d879..1e26fc2022 100644 --- a/lib/stdlib/doc/src/ordsets.xml +++ b/lib/stdlib/doc/src/ordsets.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -45,202 +45,141 @@ different if and only if they do not compare equal (<c>==</c>).</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -ordered_set() - as returned by new/0</code> - </section> + <datatypes> + <datatype> + <name name="ordset" n_vars="1"/> + <desc><p>As returned by new/0.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>new() -> Ordset</name> + <name name="new" arity="0"/> <fsummary>Return an empty set</fsummary> - <type> - <v>Ordset = ordered_set()</v> - </type> <desc> <p>Returns a new empty ordered set.</p> </desc> </func> <func> - <name>is_set(Ordset) -> bool()</name> + <name name="is_set" arity="1"/> <fsummary>Test for an <c>Ordset</c></fsummary> - <type> - <v>Ordset = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Ordset</c> is an ordered set of + <p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an ordered set of elements, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>size(Ordset) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of elements in a set</fsummary> - <type> - <v>Ordset = term()</v> - </type> <desc> - <p>Returns the number of elements in <c>Ordset</c>.</p> + <p>Returns the number of elements in <c><anno>Ordset</anno></c>.</p> </desc> </func> <func> - <name>to_list(Ordset) -> List</name> + <name name="to_list" arity="1"/> <fsummary>Convert an <c>Ordset</c>into a list</fsummary> - <type> - <v>Ordset = ordered_set()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns the elements of <c>Ordset</c> as a list.</p> + <p>Returns the elements of <c><anno>Ordset</anno></c> as a list.</p> </desc> </func> <func> - <name>from_list(List) -> Ordset</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list into an <c>Ordset</c></fsummary> - <type> - <v>List = [term()]</v> - <v>Ordset = ordered_set()</v> - </type> <desc> - <p>Returns an ordered set of the elements in <c>List</c>.</p> + <p>Returns an ordered set of the elements in <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>is_element(Element, Ordset) -> bool()</name> + <name name="is_element" arity="2"/> <fsummary>Test for membership of an <c>Ordset</c></fsummary> - <type> - <v>Element = term()</v> - <v>Ordset = ordered_set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Element</c> is an element of - <c>Ordset</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of + <c><anno>Ordset</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>add_element(Element, Ordset1) -> Ordset2</name> + <name name="add_element" arity="2"/> <fsummary>Add an element to an <c>Ordset</c></fsummary> - <type> - <v>Element = term()</v> - <v>Ordset1 = Ordset2 = ordered_set()</v> - </type> <desc> - <p>Returns a new ordered set formed from <c>Ordset1</c> with - <c>Element</c> inserted.</p> + <p>Returns a new ordered set formed from <c><anno>Ordset1</anno></c> with + <c><anno>Element</anno></c> inserted.</p> </desc> </func> <func> - <name>del_element(Element, Ordset1) -> Ordset2</name> + <name name="del_element" arity="2"/> <fsummary>Remove an element from an <c>Ordset</c></fsummary> - <type> - <v>Element = term()</v> - <v>Ordset1 = Ordset2 = ordered_set()</v> - </type> <desc> - <p>Returns <c>Ordset1</c>, but with <c>Element</c> removed.</p> + <p>Returns <c><anno>Ordset1</anno></c>, but with <c><anno>Element</anno></c> removed.</p> </desc> </func> <func> - <name>union(Ordset1, Ordset2) -> Ordset3</name> + <name name="union" arity="2"/> <fsummary>Return the union of two <c>Ordsets</c></fsummary> - <type> - <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v> - </type> <desc> - <p>Returns the merged (union) set of <c>Ordset1</c> and - <c>Ordset2</c>.</p> + <p>Returns the merged (union) set of <c><anno>Ordset1</anno></c> and + <c><anno>Ordset2</anno></c>.</p> </desc> </func> <func> - <name>union(OrdsetList) -> Ordset</name> + <name name="union" arity="1"/> <fsummary>Return the union of a list of <c>Ordsets</c></fsummary> - <type> - <v>OrdsetList = [ordered_set()]</v> - <v>Ordset = ordered_set()</v> - </type> <desc> <p>Returns the merged (union) set of the list of sets.</p> </desc> </func> <func> - <name>intersection(Ordset1, Ordset2) -> Ordset3</name> + <name name="intersection" arity="2"/> <fsummary>Return the intersection of two <c>Ordsets</c></fsummary> - <type> - <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v> - </type> <desc> - <p>Returns the intersection of <c>Ordset1</c> and - <c>Ordset2</c>.</p> + <p>Returns the intersection of <c><anno>Ordset1</anno></c> and + <c><anno>Ordset2</anno></c>.</p> </desc> </func> <func> - <name>intersection(OrdsetList) -> Ordset</name> + <name name="intersection" arity="1"/> <fsummary>Return the intersection of a list of <c>Ordsets</c></fsummary> - <type> - <v>OrdsetList = [ordered_set()]</v> - <v>Ordset = ordered_set()</v> - </type> <desc> <p>Returns the intersection of the non-empty list of sets.</p> </desc> </func> <func> - <name>is_disjoint(Ordset1, Ordset2) -> bool()</name> + <name name="is_disjoint" arity="2"/> <fsummary>Check whether two <c>Ordsets</c> are disjoint</fsummary> - <type> - <v>Ordset1 = Ordset2 = ordered_set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Ordset1</c> and - <c>Ordset2</c> are disjoint (have no elements in common), + <p>Returns <c>true</c> if <c><anno>Ordset1</anno></c> and + <c><anno>Ordset2</anno></c> are disjoint (have no elements in common), and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>subtract(Ordset1, Ordset2) -> Ordset3</name> + <name name="subtract" arity="2"/> <fsummary>Return the difference of two <c>Ordsets</c></fsummary> - <type> - <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v> - </type> <desc> - <p>Returns only the elements of <c>Ordset1</c> which are not - also elements of <c>Ordset2</c>.</p> + <p>Returns only the elements of <c><anno>Ordset1</anno></c> which are not + also elements of <c><anno>Ordset2</anno></c>.</p> </desc> </func> <func> - <name>is_subset(Ordset1, Ordset2) -> bool()</name> + <name name="is_subset" arity="2"/> <fsummary>Test for subset</fsummary> - <type> - <v>Ordset1 = Ordset2 = ordered_set()</v> - </type> <desc> - <p>Returns <c>true</c> when every element of <c>Ordset</c>1 is - also a member of <c>Ordset2</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> when every element of <c><anno>Ordset1</anno></c> is + also a member of <c><anno>Ordset2</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>fold(Function, Acc0, Ordset) -> Acc1</name> + <name name="fold" arity="3"/> <fsummary>Fold over set elements</fsummary> - <type> - <v>Function = fun (E, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Ordset = ordered_set()</v> - </type> <desc> - <p>Fold <c>Function</c> over every element in <c>Ordset</c> + <p>Fold <c><anno>Function</anno></c> over every element in <c><anno>Ordset</anno></c> returning the final value of the accumulator.</p> </desc> </func> <func> - <name>filter(Pred, Ordset1) -> Set2</name> + <name name="filter" arity="2"/> <fsummary>Filter set elements</fsummary> - <type> - <v>Pred = fun (E) -> bool()</v> - <v>Set1 = Set2 = ordered_set()</v> - </type> <desc> - <p>Filter elements in <c>Set1</c> with boolean function - <c>Fun</c>.</p> + <p>Filter elements in <c><anno>Ordset1</anno></c> with boolean function + <c><anno>Pred</anno></c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/pg.xml b/lib/stdlib/doc/src/pg.xml index b174d4f7d4..c56db8c6e6 100644 --- a/lib/stdlib/doc/src/pg.xml +++ b/lib/stdlib/doc/src/pg.xml @@ -51,77 +51,56 @@ </description> <funcs> <func> - <name>create(PgName) -> ok | {error, Reason}</name> + <name name="create" arity="1"/> <fsummary>Create an empty group</fsummary> - <type> - <v>PgName = term()</v> - <v>Reason = already_created | term()</v> - </type> <desc> - <p>Creates an empty group named <c>PgName</c> on the current + <p>Creates an empty group named <c><anno>PgName</anno></c> on the current node.</p> </desc> </func> <func> - <name>create(PgName, Node) -> ok | {error, Reason}</name> + <name name="create" arity="2"/> <fsummary>Create an empty group on another node</fsummary> - <type> - <v>PgName = term()</v> - <v>Node = node()</v> - <v>Reason = already_created | term()</v> - </type> <desc> - <p>Creates an empty group named <c>PgName</c> on the node - <c>Node</c>.</p> + <p>Creates an empty group named <c><anno>PgName</anno></c> on the node + <c><anno>Node</anno></c>.</p> </desc> </func> <func> - <name>join(PgName, Pid) -> Members</name> + <name name="join" arity="2"/> <fsummary>Join a pid to a process group</fsummary> - <type> - <v>PgName = term()</v> - <v>Pid = pid()</v> - <v>Members = [pid()]</v> - </type> <desc> - <p>Joins the pid <c>Pid</c> to the process group <c>PgName</c>. + <p>Joins the pid <c><anno>Pid</anno></c> to the process group + <c><anno>PgName</anno></c>. Returns a list of all old members of the group.</p> </desc> </func> <func> - <name>send(PgName, Msg) -> void()</name> + <name name="send" arity="2"/> <fsummary>Send a message to all members of a process group</fsummary> - <type> - <v>PgName = Msg = term()</v> - </type> <desc> <p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to - all members of the process group <c>PgName</c>.</p> - <p>Failure: <c>{badarg, {PgName, Msg}}</c> if <c>PgName</c> is + all members of the process group <c><anno>PgName</anno></c>.</p> + <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c> + if <c><anno>PgName</anno></c> is not a process group (a globally registered name).</p> </desc> </func> <func> - <name>esend(PgName, Msg) -> void()</name> + <name name="esend" arity="2"/> <fsummary>Send a message to all members of a process group, except ourselves</fsummary> - <type> - <v>PgName = Msg = term()</v> - </type> <desc> <p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to - all members of the process group <c>PgName</c>, except + all members of the process group <c><anno>PgName</anno></c>, except ourselves.</p> - <p>Failure: <c>{badarg, {PgName, Msg}}</c> if <c>PgName</c> is + <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c> + if <c><anno>PgName</anno></c> is not a process group (a globally registered name).</p> </desc> </func> <func> - <name>members(PgName) -> Members</name> + <name name="members" arity="1"/> <fsummary>Return a list of all members of a process group</fsummary> - <type> - <v>PgName = term()</v> - <v>Members = [pid()]</v> - </type> <desc> <p>Returns a list of all members of the process group <c>PgName</c>.</p> diff --git a/lib/stdlib/doc/src/pool.xml b/lib/stdlib/doc/src/pool.xml index 2b890352eb..39a79e5dc5 100644 --- a/lib/stdlib/doc/src/pool.xml +++ b/lib/stdlib/doc/src/pool.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -48,23 +48,19 @@ </description> <funcs> <func> - <name>start(Name) -></name> - <name>start(Name, Args) -> Nodes</name> + <name name="start" arity="1"/> + <name name="start" arity="2"/> <fsummary>>Start a new pool</fsummary> - <type> - <v>Name = atom()</v> - <v>Args = string()</v> - <v>Nodes = [node()]</v> - </type> <desc> <p>Starts a new pool. The file <c>.hosts.erlang</c> is read to find host names where the pool nodes can be started. See section <seealso marker="#files">Files</seealso> below. The start-up procedure fails if the file is not found.</p> <p>The slave nodes are started with <c>slave:start/2,3</c>, - passing along <c>Name</c> and, if provided, <c>Args</c>. - <c>Name</c> is used as the first part of the node names, - <c>Args</c> is used to specify command line arguments. See + passing along <c><anno>Name</anno></c> and, if provided, + <c><anno>Args</anno></c>. + <c><anno>Name</anno></c> is used as the first part of the node names, + <c><anno>Args</anno></c> is used to specify command line arguments. See <seealso marker="slave#start/2">slave(3)</seealso>.</p> <p>Access rights must be set so that all nodes in the pool have the authority to access each other.</p> @@ -73,59 +69,45 @@ </desc> </func> <func> - <name>attach(Node) -> already_attached | attached</name> + <name name="attach" arity="1"/> <fsummary>Ensure that a pool master is running</fsummary> - <type> - <v>Node = node()</v> - </type> <desc> <p>This function ensures that a pool master is running and - includes <c>Node</c> in the pool master's pool of nodes.</p> + includes <c><anno>Node</anno></c> in the pool master's pool of nodes.</p> </desc> </func> <func> - <name>stop() -> stopped</name> + <name name="stop" arity="0"/> <fsummary>Stop the pool and kill all the slave nodes</fsummary> <desc> <p>Stops the pool and kills all the slave nodes.</p> </desc> </func> <func> - <name>get_nodes() -> Nodes</name> + <name name="get_nodes" arity="0"/> <fsummary>Return a list of the current member nodes of the pool</fsummary> - <type> - <v>Nodes = [node()]</v> - </type> <desc> <p>Returns a list of the current member nodes of the pool.</p> </desc> </func> <func> - <name>pspawn(Mod, Fun, Args) -> pid()</name> + <name name="pspawn" arity="3"/> <fsummary>Spawn a process on the pool node with expected lowest future load</fsummary> - <type> - <v>Mod = Fun = atom()</v> - <v>Args = [term()]</v> - </type> <desc> <p>Spawns a process on the pool node which is expected to have the lowest future load.</p> </desc> </func> <func> - <name>pspawn_link(Mod, Fun, Args) -> pid()</name> + <name name="pspawn_link" arity="3"/> <fsummary>Spawn and link to a process on the pool node with expected lowest future load</fsummary> - <type> - <v>Mod = Fun = atom()</v> - <v>Args = [term()]</v> - </type> <desc> <p>Spawn links a process on the pool node which is expected to have the lowest future load.</p> </desc> </func> <func> - <name>get_node() -> node()</name> + <name name="get_node" arity="0"/> <fsummary>Return the node with the expected lowest future load</fsummary> <desc> <p>Returns the node with the expected lowest future load.</p> diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index 791001cb52..abc17c4a91 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -60,19 +60,33 @@ information regarding other processes which terminate as a result of this process terminating.</p> </description> + <datatypes> + <datatype> + <name name="spawn_option"/> + <desc> + <p>See <seealso marker="erts:erlang#spawn_opt/4"> + erlang:spawn_opt/2,3,4,5</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="priority_level"/> + </datatype> + <datatype> + <name name="dict_or_pid"/> + </datatype> + </datatypes> <funcs> <func> - <name>spawn(Fun) -> pid()</name> - <name>spawn(Node, Fun) -> pid()</name> - <name>spawn(Module, Function, Args) -> pid()</name> - <name>spawn(Node, Module, Function, Args) -> pid()</name> + <name name="spawn" arity="1"/> + <name name="spawn" arity="2"/> + <name name="spawn" arity="3"/> + <name name="spawn" arity="4"/> <fsummary>Spawn a new process.</fsummary> - <type> - <v>Node = node()</v> - <v>Fun = fun() -> void()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> + <type variable="Node"/> + <type variable="Fun" name_i="1"/> + <type variable="Module"/> + <type variable="Function"/> + <type variable="Args"/> <desc> <p>Spawns a new process and initializes it as described above. The process is spawned using the @@ -80,17 +94,16 @@ </desc> </func> <func> - <name>spawn_link(Fun) -> pid()</name> - <name>spawn_link(Node, Fun) -> pid()</name> - <name>spawn_link(Module, Function, Args) -> pid()</name> - <name>spawn_link(Node, Module, Function, Args) -> pid()</name> + <name name="spawn_link" arity="1"/> + <name name="spawn_link" arity="2"/> + <name name="spawn_link" arity="3"/> + <name name="spawn_link" arity="4"/> <fsummary>Spawn and link to a new process.</fsummary> - <type> - <v>Node = node()</v> - <v>Fun = fun() -> void()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> + <type variable="Node"/> + <type variable="Fun" name_i="1"/> + <type variable="Module"/> + <type variable="Function"/> + <type variable="Args"/> <desc> <p>Spawns a new process and initializes it as described above. The process is spawned using the @@ -99,18 +112,17 @@ </desc> </func> <func> - <name>spawn_opt(Fun, SpawnOpts) -> pid()</name> - <name>spawn_opt(Node, Fun, SpawnOpts) -> pid()</name> - <name>spawn_opt(Module, Function, Args, SpawnOpts) -> pid()</name> - <name>spawn_opt(Node, Module, Func, Args, SpawnOpts) -> pid()</name> + <name name="spawn_opt" arity="2"/> + <name name="spawn_opt" arity="3"/> + <name name="spawn_opt" arity="4"/> + <name name="spawn_opt" arity="5"/> <fsummary>Spawn a new process with given options.</fsummary> - <type> - <v>Node = node()</v> - <v>Fun = fun() -> void()</v> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>SpawnOpts -- see erlang:spawn_opt/2,3,4,5</v> - </type> + <type variable="Node"/> + <type variable="Fun" name_i="1"/> + <type variable="Module"/> + <type variable="Function"/> + <type variable="Args"/> + <type variable="SpawnOpts"/> <desc> <p>Spawns a new process and initializes it as described above. The process is spawned using the @@ -124,20 +136,13 @@ </desc> </func> <func> - <name>start(Module, Function, Args) -> Ret</name> - <name>start(Module, Function, Args, Time) -> Ret</name> - <name>start(Module, Function, Args, Time, SpawnOpts) -> Ret</name> - <name>start_link(Module, Function, Args) -> Ret</name> - <name>start_link(Module, Function, Args, Time) -> Ret</name> - <name>start_link(Module, Function, Args, Time, SpawnOpts) -> Ret</name> + <name name="start" arity="3"/> + <name name="start" arity="4"/> + <name name="start" arity="5"/> + <name name="start_link" arity="3"/> + <name name="start_link" arity="4"/> + <name name="start_link" arity="5"/> <fsummary>Start a new process synchronously.</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - <v>Time = int() >= 0 | infinity</v> - <v>SpawnOpts -- see erlang:spawn_opt/2,3,4,5</v> - <v>Ret = term() | {error, Reason}</v> - </type> <desc> <p>Starts a new process synchronously. Spawns the process and waits for it to start. When the process has started, it @@ -148,13 +153,13 @@ function. At this time, <c>Ret</c> is returned.</p> <p>If the <c>start_link/3,4,5</c> function is used and the process crashes before it has called <c>init_ack/1,2</c>, - <c>{error, Reason}</c> is returned if the calling process + <c>{error, <anno>Reason</anno>}</c> is returned if the calling process traps exits.</p> - <p>If <c>Time</c> is specified as an integer, this function - waits for <c>Time</c> milliseconds for the new process to call + <p>If <c><anno>Time</anno></c> is specified as an integer, this function + waits for <c><anno>Time</anno></c> milliseconds for the new process to call <c>init_ack</c>, or <c>{error, timeout}</c> is returned, and the process is killed.</p> - <p>The <c>SpawnOpts</c> argument, if given, will be passed + <p>The <c><anno>SpawnOpts</anno></c> argument, if given, will be passed as the last argument to the <c>spawn_opt/2,3,4,5</c> BIF.</p> <note> <p>Using the spawn option <c>monitor</c> is currently not @@ -164,17 +169,13 @@ </desc> </func> <func> - <name>init_ack(Parent, Ret) -> void()</name> - <name>init_ack(Ret) -> void()</name> + <name name="init_ack" arity="1"/> + <name name="init_ack" arity="2"/> <fsummary>Used by a process when it has started.</fsummary> - <type> - <v>Parent = pid()</v> - <v>Ret = term()</v> - </type> <desc> <p>This function must used by a process that has been started by a <seealso marker="#start/3">start[_link]/3,4,5</seealso> - function. It tells <c>Parent</c> that the process has + function. It tells <c><anno>Parent</anno></c> that the process has initialized itself, has started, or has failed to initialize itself.</p> <p>The <c>init_ack/1</c> function uses the parent value @@ -205,40 +206,30 @@ init(Parent) -> </desc> </func> <func> - <name>format(CrashReport) -> string()</name> + <name name="format" arity="1"/> <fsummary>Format a crash report.</fsummary> - <type> - <v>CrashReport = term()</v> - </type> <desc> <p>This function can be used by a user defined event handler to format a crash report. The crash report is sent using - <c>error_logger:error_report(crash_report, CrashReport)</c>. + <c>error_logger:error_report(crash_report, <anno>CrashReport</anno>)</c>. That is, the event to be handled is of the format - <c>{error_report, GL, {Pid, crash_report, CrashReport}}</c> + <c>{error_report, GL, {Pid, crash_report, <anno>CrashReport</anno>}}</c> where <c>GL</c> is the group leader pid of the process <c>Pid</c> which sent the crash report.</p> </desc> </func> <func> - <name>initial_call(Process) -> {Module,Function,Args} | false</name> + <name name="initial_call" arity="1"/> <fsummary>Extract the initial call of a <c>proc_lib</c>spawned process.</fsummary> - <type> - <v>Process = pid() | {X,Y,Z} | ProcInfo</v> - <v> X = Y = Z = int()</v> - <v> ProcInfo = term()</v> - <v>Module = Function = atom()</v> - <v>Args = [atom()]</v> - </type> <desc> <p>Extracts the initial call of a process that was started using one of the spawn or start functions described above. - <c>Process</c> can either be a pid, an integer tuple (from + <c><anno>Process</anno></c> can either be a pid, an integer tuple (from which a pid can be created), or the process information of a process <c>Pid</c> fetched through an <c>erlang:process_info(Pid)</c> function call.</p> - <note><p>The list <c>Args</c> no longer contains the actual arguments, + <note><p>The list <c><anno>Args</anno></c> no longer contains the actual arguments, but the same number of atoms as the number of arguments; the first atom is always <c>'Argument__1'</c>, the second <c>'Argument__2'</c>, and so on. The reason is that the argument list could waste a significant @@ -256,23 +247,15 @@ init(Parent) -> </desc> </func> <func> - <name>translate_initial_call(Process) -> {Module,Function,Arity} | Fun</name> + <name name="translate_initial_call" arity="1"/> <fsummary>Extract and translate the initial call of a <c>proc_lib</c>spawned process.</fsummary> - <type> - <v>Process = pid() | {X,Y,Z} | ProcInfo</v> - <v> X = Y = Z = int()</v> - <v> ProcInfo = term()</v> - <v>Module = Function = atom()</v> - <v>Arity = int()</v> - <v>Fun = fun() -> void()</v> - </type> <desc> <p>This function is used by the <c>c:i/0</c> and <c>c:regs/0</c> functions in order to present process information.</p> <p>Extracts the initial call of a process that was started using one of the spawn or start functions described above, - and translates it to more useful information. <c>Process</c> + and translates it to more useful information. <c><anno>Process</anno></c> can either be a pid, an integer tuple (from which a pid can be created), or the process information of a process <c>Pid</c> fetched through an <c>erlang:process_info(Pid)</c> @@ -280,15 +263,15 @@ init(Parent) -> <p>If the initial call is to one of the system defined behaviors such as <c>gen_server</c> or <c>gen_event</c>, it is translated to more useful information. If a <c>gen_server</c> - is spawned, the returned <c>Module</c> is the name of - the callback module and <c>Function</c> is <c>init</c> + is spawned, the returned <c><anno>Module</anno></c> is the name of + the callback module and <c><anno>Function</anno></c> is <c>init</c> (the function that initiates the new server).</p> <p>A <c>supervisor</c> and a <c>supervisor_bridge</c> are also <c>gen_server</c> processes. In order to return information that this process is a supervisor and the name of the - call-back module, <c>Module</c> is <c>supervisor</c> and - <c>Function</c> is the name of the supervisor callback - module. <c>Arity</c> is <c>1</c> since the <c>init/1</c> + call-back module, <c><anno>Module</anno></c> is <c>supervisor</c> and + <c><anno>Function</anno></c> is the name of the supervisor callback + module. <c><anno>Arity</anno></c> is <c>1</c> since the <c>init/1</c> function is called initially in the callback module.</p> <p>By default, <c>{proc_lib,init_p,5}</c> is returned if no information about the initial call can be found. It is @@ -297,12 +280,8 @@ init(Parent) -> </desc> </func> <func> - <name>hibernate(Module, Function, Args)</name> + <name name="hibernate" arity="3"/> <fsummary>Hibernate a process until a message is sent to it</fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Args = [term()]</v> - </type> <desc> <p>This function does the same as (and does call) the BIF <seealso marker="erts:erlang#erlang:hibernate/3">hibernate/3</seealso>, diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml index 9f1c5b24ad..225c5e97eb 100644 --- a/lib/stdlib/doc/src/proplists.xml +++ b/lib/stdlib/doc/src/proplists.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2002</year><year>2010</year> + <year>2002</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -48,14 +48,15 @@ words, numbers are compared literally rather than by value, so that, for instance, <c>1</c> and <c>1.0</c> are different keys.</p> </description> + <datatypes> + <datatype> + <name name="property"/> + </datatype> + </datatypes> <funcs> <func> - <name>append_values(Key, List) -> List</name> + <name name="append_values" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Similar to <c>get_all_values/2</c>, but each value is wrapped in a list unless it is already itself a list, and the @@ -65,11 +66,8 @@ </desc> </func> <func> - <name>compact(List) -> List</name> + <name name="compact" arity="1"/> <fsummary></fsummary> - <type> - <v>List = [term()]</v> - </type> <desc> <p>Minimizes the representation of all entries in the list. This is equivalent to <c><![CDATA[[property(P) || P <- List]]]></c>.</p> @@ -77,33 +75,24 @@ </desc> </func> <func> - <name>delete(Key, List) -> List</name> + <name name="delete" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Deletes all entries associated with <c>Key</c> from - <c>List</c>.</p> + <p>Deletes all entries associated with <c><anno>Key</anno></c> from + <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>expand(Expansions, List) -> List</name> + <name name="expand" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>Expansions = [{Property,[term()]}]</v> - <v>Property = atom() | tuple()</v> - </type> <desc> <p>Expands particular properties to corresponding sets of - properties (or other terms). For each pair <c>{Property, Expansion}</c> in <c>Expansions</c>, if <c>E</c> is - the first entry in <c>List</c> with the same key as - <c>Property</c>, and <c>E</c> and <c>Property</c> + properties (or other terms). For each pair <c>{<anno>Property</anno>, <anno>Expansion</anno>}</c> in <c><anno>Expansions</anno></c>, if <c>E</c> is + the first entry in <c><anno>List</anno></c> with the same key as + <c><anno>Property</anno></c>, and <c>E</c> and <c><anno>Property</anno></c> have equivalent normal forms, then <c>E</c> is replaced with - the terms in <c>Expansion</c>, and any following entries with - the same key are deleted from <c>List</c>.</p> + the terms in <c><anno>Expansion</anno></c>, and any following entries with + the same key are deleted from <c><anno>List</anno></c>.</p> <p>For example, the following expressions all return <c>[fie, bar, baz, fum]</c>:</p> <code type="none"> expand([{foo, [bar, baz]}], @@ -120,103 +109,75 @@ <p>Note that if the original property term is to be preserved in the result when expanded, it must be included in the expansion list. The inserted terms are not expanded recursively. If - <c>Expansions</c> contains more than one property with the same + <c><anno>Expansions</anno></c> contains more than one property with the same key, only the first occurrence is used.</p> <p>See also: <c>normalize/2</c>.</p> </desc> </func> <func> - <name>get_all_values(Key, List) -> [term()]</name> + <name name="get_all_values" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Similar to <c>get_value/2</c>, but returns the list of values for <em>all</em> entries <c>{Key, Value}</c> in - <c>List</c>. If no such entry exists, the result is the empty + <c><anno>List</anno></c>. If no such entry exists, the result is the empty list.</p> <p>See also: <c>get_value/2</c>.</p> </desc> </func> <func> - <name>get_bool(Key, List) -> bool()</name> + <name name="get_bool" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Returns the value of a boolean key/value option. If - <c>lookup(Key, List)</c> would yield <c>{Key, true}</c>, + <c>lookup(<anno>Key</anno>, <anno>List</anno>)</c> would yield <c>{<anno>Key</anno>, true}</c>, this function returns <c>true</c>; otherwise <c>false</c> is returned.</p> <p>See also: <c>get_value/2</c>, <c>lookup/2</c>.</p> </desc> </func> <func> - <name>get_keys(List) -> [term()]</name> + <name name="get_keys" arity="1"/> <fsummary></fsummary> - <type> - <v>List = [term()]</v> - </type> <desc> - <p>Returns an unordered list of the keys used in <c>List</c>, + <p>Returns an unordered list of the keys used in <c><anno>List</anno></c>, not containing duplicates.</p> </desc> </func> <func> - <name>get_value(Key, List) -> term()</name> + <name name="get_value" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Equivalent to <c>get_value(Key, List, undefined)</c>.</p> + <p>Equivalent to <c>get_value(<anno>Key</anno>, <anno>List</anno>, undefined)</c>.</p> </desc> </func> <func> - <name>get_value(Key, List, Default) -> term()</name> + <name name="get_value" arity="3"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>Default = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Returns the value of a simple key/value property in - <c>List</c>. If <c>lookup(Key, List)</c> would yield - <c>{Key, Value}</c>, this function returns the corresponding - <c>Value</c>, otherwise <c>Default</c> is returned.</p> + <c><anno>List</anno></c>. If <c>lookup(<anno>Key</anno>, <anno>List</anno>)</c> would yield + <c>{<anno>Key</anno>, Value}</c>, this function returns the corresponding + <c>Value</c>, otherwise <c><anno>Default</anno></c> is returned.</p> <p>See also: <c>get_all_values/2</c>, <c>get_bool/2</c>, <c>get_value/2</c>, <c>lookup/2</c>.</p> </desc> </func> <func> - <name>is_defined(Key, List) -> bool()</name> + <name name="is_defined" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns <c>true</c> if <c>List</c> contains at least - one entry associated with <c>Key</c>, otherwise + <p>Returns <c>true</c> if <c><anno>List</anno></c> contains at least + one entry associated with <c><anno>Key</anno></c>, otherwise <c>false</c> is returned.</p> </desc> </func> <func> - <name>lookup(Key, List) -> none | tuple()</name> + <name name="lookup" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns the first entry associated with <c>Key</c> in - <c>List</c>, if one exists, otherwise returns + <p>Returns the first entry associated with <c><anno>Key</anno></c> in + <c><anno>List</anno></c>, if one exists, otherwise returns <c>none</c>. For an atom <c>A</c> in the list, the tuple <c>{A, true}</c> is the entry associated with <c>A</c>.</p> <p>See also: <c>get_bool/2</c>, <c>get_value/2</c>, @@ -224,34 +185,20 @@ </desc> </func> <func> - <name>lookup_all(Key, List) -> [tuple()]</name> + <name name="lookup_all" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns the list of all entries associated with <c>Key</c> - in <c>List</c>. If no such entry exists, the result is the + <p>Returns the list of all entries associated with <c><anno>Key</anno></c> + in <c><anno>List</anno></c>. If no such entry exists, the result is the empty list.</p> <p>See also: <c>lookup/2</c>.</p> </desc> </func> <func> - <name>normalize(List, Stages) -> List</name> + <name name="normalize" arity="2"/> <fsummary></fsummary> - <type> - <v>List = [term()]</v> - <v>Stages = [Operation]</v> - <v>Operation = {aliases, Aliases} | {negations, Negations} | {expand, Expansions}</v> - <v>Aliases = [{Key, Key}]</v> - <v>Negations = [{Key, Key}]</v> - <v>Key = term()</v> - <v>Expansions = [{Property, [term()]}]</v> - <v>Property = atom() | tuple()</v> - </type> <desc> - <p>Passes <c>List</c> through a sequence of + <p>Passes <c><anno>List</anno></c> through a sequence of substitution/expansion stages. For an <c>aliases</c> operation, the function <c>substitute_aliases/2</c> is applied using the given list of aliases; for a <c>negations</c> operation, @@ -270,51 +217,37 @@ </desc> </func> <func> - <name>property(Property) -> Property</name> + <name name="property" arity="1"/> <fsummary></fsummary> - <type> - <v>Property = atom() | tuple()</v> - </type> <desc> <p>Creates a normal form (minimal) representation of a property. If - <c>Property</c> is <c>{Key, true}</c> where <c>Key</c> is + <c><anno>Property</anno></c> is <c>{Key, true}</c> where <c>Key</c> is an atom, this returns <c>Key</c>, otherwise the whole term - <c>Property</c> is returned.</p> + <c><anno>Property</anno></c> is returned.</p> <p>See also: <c>property/2</c>.</p> </desc> </func> <func> - <name>property(Key, Value) -> Property</name> + <name name="property" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = term()</v> - <v>Value = term()</v> - <v>Property = atom() | tuple()</v> - </type> <desc> <p>Creates a normal form (minimal) representation of a simple - key/value property. Returns <c>Key</c> if <c>Value</c> is - <c>true</c> and <c>Key</c> is an atom, otherwise a tuple - <c>{Key, Value}</c> is returned.</p> + key/value property. Returns <c><anno>Key</anno></c> if <c><anno>Value</anno></c> is + <c>true</c> and <c><anno>Key</anno></c> is an atom, otherwise a tuple + <c>{<anno>Key</anno>, <anno>Value</anno>}</c> is returned.</p> <p>See also: <c>property/1</c>.</p> </desc> </func> <func> - <name>split(List, Keys) -> {Lists, Rest}</name> + <name name="split" arity="2"/> <fsummary></fsummary> - <type> - <v>List = [term()]</v> - <v>Keys = [term()]</v> - <v>Lists = [[term()]]</v> - <v>Rest = [term()]</v> - </type> <desc> - <p>Partitions <c>List</c> into a list of sublists and a - remainder. <c>Lists</c> contains one sublist for each key in - <c>Keys</c>, in the corresponding order. The relative order of + <p>Partitions <c><anno>List</anno></c> into a list of sublists and a + remainder. <c><anno>Lists</anno></c> contains one sublist for each key in + <c><anno>Keys</anno></c>, in the corresponding order. The relative order of the elements in each sublist is preserved from the original - <c>List</c>. <c>Rest</c> contains the elements in - <c>List</c> that are not associated with any of the given keys, + <c><anno>List</anno></c>. <c><anno>Rest</anno></c> contains the elements in + <c><anno>List</anno></c> that are not associated with any of the given keys, also with their original relative order preserved.</p> <p>Example: split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</p> @@ -323,19 +256,14 @@ </desc> </func> <func> - <name>substitute_aliases(Aliases, List) -> List</name> + <name name="substitute_aliases" arity="2"/> <fsummary></fsummary> - <type> - <v>Aliases = [{Key, Key}]</v> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Substitutes keys of properties. For each entry in - <c>List</c>, if it is associated with some key <c>K1</c> - such that <c>{K1, K2}</c> occurs in <c>Aliases</c>, the - key of the entry is changed to <c>Key2</c>. If the same - <c>K1</c> occurs more than once in <c>Aliases</c>, only + <c><anno>List</anno></c>, if it is associated with some key <c>K1</c> + such that <c>{K1, K2}</c> occurs in <c><anno>Aliases</anno></c>, the + key of the entry is changed to <c>K2</c>. If the same + <c>K1</c> occurs more than once in <c><anno>Aliases</anno></c>, only the first occurrence is used.</p> <p>Example: <c>substitute_aliases([{color, colour}], L)</c> will replace all tuples <c>{color, ...}</c> in <c>L</c> @@ -345,24 +273,19 @@ </desc> </func> <func> - <name>substitute_negations(Negations, List) -> List</name> + <name name="substitute_negations" arity="2"/> <fsummary></fsummary> - <type> - <v>Negations = [{Key, Key}]</v> - <v>Key = term()</v> - <v>List = [term()]</v> - </type> <desc> <p>Substitutes keys of boolean-valued properties and simultaneously negates their values. For each entry in - <c>List</c>, if it is associated with some key <c>K1</c> - such that <c>{K1, K2}</c> occurs in <c>Negations</c>, then + <c><anno>List</anno></c>, if it is associated with some key <c>K1</c> + such that <c>{K1, K2}</c> occurs in <c><anno>Negations</anno></c>, then if the entry was <c>{K1, true}</c> it will be replaced with <c>{K2, false}</c>, otherwise it will be replaced with <c>{K2, true}</c>, thus changing the name of the option and simultaneously negating the value given by <c>get_bool(List)</c>. If the same <c>K1</c> occurs more - than once in <c>Negations</c>, only the first occurrence is + than once in <c><anno>Negations</anno></c>, only the first occurrence is used.</p> <p>Example: <c>substitute_negations([{no_foo, foo}], L)</c> will replace any atom <c>no_foo</c> or tuple @@ -374,13 +297,10 @@ </desc> </func> <func> - <name>unfold(List) -> List</name> + <name name="unfold" arity="1"/> <fsummary></fsummary> - <type> - <v>List = [term()]</v> - </type> <desc> - <p>Unfolds all occurrences of atoms in <c>List</c> to tuples + <p>Unfolds all occurrences of atoms in <c><anno>List</anno></c> to tuples <c>{Atom, true}</c>.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/qlc.xml b/lib/stdlib/doc/src/qlc.xml index da24ee9914..ce50631ca9 100644 --- a/lib/stdlib/doc/src/qlc.xml +++ b/lib/stdlib/doc/src/qlc.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -45,7 +45,9 @@ tables</em>. Typical QLC tables are ETS, Dets, and Mnesia tables. There is also support for user defined tables, see the <seealso marker="#implementing_a_qlc_table">Implementing a QLC - table</seealso> section. A <em>query</em> is stated using + table</seealso> section. <marker + id="query_list_comprehension"></marker> + A <em>query</em> is stated using <em>Query List Comprehensions</em> (QLCs). The answers to a query are determined by data in QLC tables that fulfill the constraints expressed by the QLCs of the query. QLCs are similar @@ -55,10 +57,11 @@ fact, in the absence of optimizations and options such as <c>cache</c> and <c>unique</c> (see below), every QLC free of QLC tables evaluates to the same list of answers as the - identical ordinary list comprehension. </p> + identical ordinary list comprehension.</p> <p>While ordinary list comprehensions evaluate to lists, calling - <seealso marker="#q">qlc:q/1,2</seealso> returns a <em>Query + <seealso marker="#q">qlc:q/1,2</seealso> returns a <marker + id="query_handle"></marker><em> Query Handle</em>. To obtain all the answers to a query, <seealso marker="#eval">qlc:eval/1,2</seealso> should be called with the query handle as first argument. Query handles are essentially @@ -69,7 +72,8 @@ Code replacement is described in the <seealso marker="doc/reference_manual:code_loading">Erlang Reference Manual</seealso>. The list of answers can also be traversed in - chunks by use of a <em>Query Cursor</em>. Query cursors are + chunks by use of a <marker + id="query_cursor"></marker><em>Query Cursor</em>. Query cursors are created by calling <seealso marker="#cursor">qlc:cursor/1,2</seealso> with a query handle as first argument. Query cursors are essentially Erlang processes. @@ -226,75 +230,6 @@ </section> - <section><title>Common data types</title> - - <list type="bulleted"> - <item><p><c>QueryCursor = {qlc_cursor, term()}</c></p> - </item> - <item><p><c>QueryHandle = {qlc_handle, term()}</c></p> - </item> - <item><p><c>QueryHandleOrList = QueryHandle | list()</c></p> - </item> - <item><p><c>Answers = [Answer]</c></p> - </item> - <item><p><c>Answer = term()</c></p> - </item> - <item><p><c>AbstractExpression = </c> - parse trees - for Erlang expressions, see the <seealso - marker="erts:absform">abstract format</seealso> - documentation in the ERTS User's Guide -</p> - </item> - <item><p><c>MatchExpression = </c> - - match specifications, see the <seealso - marker="erts:match_spec">match specification</seealso> - documentation in the ERTS User's Guide and <seealso - marker="ms_transform">ms_transform(3)</seealso> -</p> - </item> - <item><p><c>SpawnOptions = default | spawn_options()</c></p> - </item> - <item><p><c>SortOptions = [SortOption] | SortOption</c></p> - </item> - <item><p><c>SortOption = {compressed, bool()} - | {no_files, NoFiles} - | {order, Order} - | {size, Size} - | {tmpdir, TempDirectory} - | {unique, bool()} </c> - - see <seealso - marker="file_sorter">file_sorter(3)</seealso> -</p> - </item> - <item><p><c>Order = ascending | descending | OrderFun</c></p> - </item> - <item><p><c>OrderFun = fun(term(), term()) -> bool()</c></p> - </item> - <item><p><c>TempDirectory = "" | filename()</c></p> - </item> - <item><p><c>Size = int() > 0</c></p> - </item> - <item><p><c>NoFiles = int() > 1</c></p> - </item> - <item><p><c>KeyPos = int() > 0 | [int() > 0]</c></p> - </item> - <item><p><c>MaxListSize = int() >= 0</c></p> - </item> - <item><p><c>bool() = true | false</c></p> - </item> - <item><p><c>Cache = ets | list | no</c></p> - </item> - <item><p><c>TmpFileUsage = allowed | not_allowed | info_msg - | warning_msg | error_msg</c></p> - </item> - <item><p><c>filename() = </c> - see <seealso - marker="filename">filename(3)</seealso> -</p> - </item> - <item><p><c>spawn_options() = </c> - see <seealso - marker="erts:erlang">erlang(3)</seealso> -</p> - </item> - - </list> - - </section> - <section><title>Getting started</title> <p><marker id="getting_started"></marker> As already mentioned @@ -679,34 +614,104 @@ ets:match_spec_run(ets:lookup(86033, {2,2}), </section> + <datatypes> + <datatype> + <name name="abstract_expr"></name> + <desc><p>Parse trees for Erlang expression, see the <seealso + marker="erts:absform">abstract format</seealso> + documentation in the ERTS User's Guide.</p></desc> + </datatype> + <datatype> + <name name="answer"></name> + </datatype> + <datatype> + <name name="answers"></name> + </datatype> + <datatype> + <name name="cache"></name> + </datatype> + <datatype> + <name name="match_expression"></name> + <desc><p>Match specification, see the <seealso + marker="erts:match_spec">match specification</seealso> + documentation in the ERTS User's Guide and <seealso + marker="ms_transform">ms_transform(3).</seealso></p></desc> + </datatype> + <datatype> + <name name="no_files"></name> + <desc><p>Actually an integer > 1.</p></desc> + </datatype> + <datatype> + <name name="key_pos"></name> + </datatype> + <datatype> + <name name="max_list_size"></name> + </datatype> + <datatype> + <name name="order"></name> + </datatype> + <datatype> + <name name="order_fun"></name> + </datatype> + <datatype> + <name name="query_cursor"></name> + <desc><p>A <seealso marker="#query_cursor">query cursor</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="query_handle"></name> + <desc><p>A <seealso marker="#query_handle">query handle</seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="query_handle_or_list"></name> + </datatype> + <datatype> + <name name="query_list_comprehension"></name> + <desc><p>A literal + <seealso marker="#query_list_comprehension">query + list comprehension</seealso>.</p></desc> + </datatype> + <datatype> + <name name="spawn_options"></name> + </datatype> + <datatype> + <name name="sort_options"></name> + </datatype> + <datatype> + <name name="sort_option"></name> + <desc><p>See <seealso + marker="file_sorter">file_sorter(3)</seealso>.</p></desc> + </datatype> + <datatype> + <name name="tmp_directory"></name> + </datatype> + <datatype> + <name name="tmp_file_usage"></name> + </datatype> + </datatypes> + <funcs> <func> - <name>append(QHL) -> QH</name> + <name name="append" arity="1"/> <fsummary>Return a query handle.</fsummary> - <type> - <v>QHL = [QueryHandleOrList]</v> - <v>QH = QueryHandle</v> - </type> <desc> <p>Returns a query handle. When evaluating the query handle - <c>QH</c> all answers to the first query handle in - <c>QHL</c> is returned followed by all answers to the rest - of the query handles in <c>QHL</c>.</p> + <c><anno>QH</anno></c> all answers to the first query handle in + <c><anno>QHL</anno></c> are returned followed by all answers + to the rest of the query handles in <c><anno>QHL</anno></c>.</p> </desc> </func> <func> - <name>append(QH1, QH2) -> QH3</name> + <name name="append" arity="2"/> <fsummary>Return a query handle.</fsummary> - <type> - <v>QH1 = QH2 = QueryHandleOrList</v> - <v>QH3 = QueryHandle</v> - </type> <desc> <p>Returns a query handle. When evaluating the query handle - <c>QH3</c> all answers to <c>QH1</c> are returned followed - by all answers to <c>QH2</c>.</p> + <c><anno>QH3</anno></c> all answers to + <c><anno>QH1</anno></c> are returned followed by all answers + to <c><anno>QH2</anno></c>.</p> <p><c>append(QH1, QH2)</c> is equivalent to <c>append([QH1, QH2])</c>.</p> @@ -714,17 +719,9 @@ ets:match_spec_run(ets:lookup(86033, {2,2}), </func> <func> - <name>cursor(QueryHandleOrList [, Options]) -> QueryCursor</name> + <name name="cursor" arity="1"/> + <name name="cursor" arity="2"/> <fsummary>Create a query cursor.</fsummary> - <type> - <v>Options = [Option] | Option</v> - <v>Option = {cache_all, Cache} | cache_all - | {max_list_size, MaxListSize} - | {spawn_options, SpawnOptions} - | {tmpdir_usage, TmpFileUsage} - | {tmpdir, TempDirectory} - | {unique_all, bool()} | unique_all</v> - </type> <desc> <p><marker id="cursor"></marker>Creates a query cursor and makes the calling process the owner of the cursor. The @@ -746,11 +743,13 @@ ets:match_spec_run(ets:lookup(86033, {2,2}), [{b,1},{b,2}] 4> <input>qlc:delete_cursor(QC).</input> ok</pre> + <p><c>cursor(<anno>QH</anno>)</c> is equivalent to + <c>cursor(<anno>QH</anno>, [])</c>.</p> </desc> </func> <func> - <name>delete_cursor(QueryCursor) -> ok</name> + <name name="delete_cursor" arity="1"/> <fsummary>Delete a query cursor.</fsummary> <desc> <p>Deletes a query cursor. Only the owner of the cursor can @@ -759,19 +758,11 @@ ok</pre> </func> <func> - <name>eval(QueryHandleOrList [, Options]) -> Answers | Error</name> - <name>e(QueryHandleOrList [, Options]) -> Answers</name> + <name name="eval" arity="1"/> + <name name="eval" arity="2"/> + <name name="e" arity="1"/> + <name name="e" arity="2"/> <fsummary>Return all answers to a query.</fsummary> - <type> - <v>Options = [Option] | Option</v> - <v>Option = {cache_all, Cache} | cache_all - | {max_list_size, MaxListSize} - | {tmpdir_usage, TmpFileUsage} - | {tmpdir, TempDirectory} - | {unique_all, bool()} | unique_all</v> - <v>Error = {error, module(), Reason}</v> - <v>Reason = - as returned by file_sorter(3) -</v> - </type> <desc> <p><marker id="eval"></marker>Evaluates a query handle in the calling process and collects all answers in a list.</p> @@ -780,47 +771,39 @@ ok</pre> 1> <input>QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),</input> <input>qlc:eval(QH).</input> [{a,1},{a,2},{b,1},{b,2}]</pre> + <p><c>eval(<anno>QH</anno>)</c> is equivalent to + <c>eval(<anno>QH</anno>, [])</c>.</p> </desc> </func> <func> - <name>fold(Function, Acc0, QueryHandleOrList [, Options]) -> - Acc1 | Error</name> + <name name="fold" arity="3"/> + <name name="fold" arity="4"/> <fsummary>Fold a function over the answers to a query.</fsummary> - <type> - <v>Function = fun(Answer, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Options = [Option] | Option</v> - <v>Option = {cache_all, Cache} | cache_all - | {max_list_size, MaxListSize} - | {tmpdir_usage, TmpFileUsage} - | {tmpdir, TempDirectory} - | {unique_all, bool()} | unique_all</v> - <v>Error = {error, module(), Reason}</v> - <v>Reason = - as returned by file_sorter(3) -</v> - </type> <desc> - <p>Calls <c>Function</c> on successive answers to the query - handle together with an extra argument <c>AccIn</c>. The - query handle and the function are evaluated in the calling - process. <c>Function</c> must return a new accumulator which - is passed to the next call. <c>Acc0</c> is returned if there - are no answers to the query handle.</p> + <p>Calls <c><anno>Function</anno></c> on successive answers to + the query handle together with an extra argument + <c><anno>AccIn</anno></c>. The query handle and the function + are evaluated in the calling process. + <c><anno>Function</anno></c> must return a new accumulator + which is passed to the next call. + <c><anno>Acc0</anno></c> is returned if there are no answers + to the query handle.</p> <pre> 1> <input>QH = [1,2,3,4,5,6],</input> <input>qlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).</input> 21</pre> + <p><c>fold(<anno>Function</anno>, <anno>Acc0</anno>, + <anno>QH</anno>)</c> is equivalent to + <c>fold(<anno>Function</anno>, <anno>Acc0</anno>, + <anno>QH</anno>, [])</c>.</p> </desc> </func> <func> - <name>format_error(Error) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Return an English description of a an error tuple.</fsummary> - <type> - <v>Error = {error, module(), term()}</v> - <v>Chars = [char() | Chars]</v> - </type> <desc> <p>Returns a descriptive string in English of an error tuple returned by some of the functions of the <c>qlc</c> module @@ -830,25 +813,9 @@ ok</pre> </func> <func> - <name>info(QueryHandleOrList [, Options]) -> Info</name> + <name name="info" arity="1"/> + <name name="info" arity="2"/> <fsummary>Return code describing a query handle.</fsummary> - <type> - <v>Options = [Option] | Option</v> - <v>Option = EvalOption | ReturnOption</v> - <v>EvalOption = {cache_all, Cache} | cache_all - | {max_list_size, MaxListSize} - | {tmpdir_usage, TmpFileUsage} - | {tmpdir, TempDirectory} - | {unique_all, bool()} | unique_all</v> - <v>ReturnOption = {depth, Depth} - | {flat, bool()} - | {format, Format} - | {n_elements, NElements}</v> - <v>Depth = infinity | int() >= 0</v> - <v>Format = abstract_code | string</v> - <v>NElements = infinity | int() > 0</v> - <v>Info = AbstractExpression | string()</v> - </type> <desc> <p><marker id="info"></marker>Returns information about a query handle. The information describes the simplifications @@ -879,18 +846,18 @@ ok</pre> <input>io:format("~s~n", [qlc:info(QH, unique_all)]).</input> begin V1 = - qlc:q([ + qlc:q([ SQV || SQV <- [x,y] ], [{unique,true}]), V2 = - qlc:q([ + qlc:q([ SQV || SQV <- [a,b] ], [{unique,true}]), - qlc:q([ + qlc:q([ {X,Y} || X <- V1, Y <- V2 @@ -913,19 +880,19 @@ end</pre> <input>io:format("~s~n", [qlc:info(Q)]).</input> begin V1 = - qlc:q([ + qlc:q([ P0 || P0 = {W,Y} <- ets:table(17) ]), V2 = - qlc:q([ + qlc:q([ [G1|G2] || G2 <- V1, G1 <- ets:table(16), element(2, G1) =:= element(1, G2) ], [{join,lookup}]), - qlc:q([ + qlc:q([ {X,Z,W} || [{X,Z}|{W,Y}] <- V2 ]) @@ -936,44 +903,43 @@ end</pre> method chosen. A convention is used for lookup join: the first generator (<c>G2</c>) is the one traversed, the second one (<c>G1</c>) is the table where constants are looked up.</p> + + <p><c>info(<anno>QH</anno>)</c> is equivalent to + <c>info(<anno>QH</anno>, [])</c>.</p> </desc> </func> <func> - <name>keysort(KeyPos, QH1 [, SortOptions]) -> QH2</name> + <name name="keysort" arity="2"/> + <name name="keysort" arity="3"/> <fsummary>Return a query handle.</fsummary> - <type> - <v>QH1 = QueryHandleOrList</v> - <v>QH2 = QueryHandle</v> - </type> <desc> <p>Returns a query handle. When evaluating the query handle - <c>QH2</c> the answers to the query handle <c>QH1</c> are - sorted by <seealso + <c><anno>QH2</anno></c> the answers to the query handle + <c><anno>QH1</anno></c> are sorted by <seealso marker="file_sorter">file_sorter:keysort/4</seealso> according to the options.</p> - <p>The sorter will use temporary files only if <c>QH1</c> does - not evaluate to a list and the size of the binary - representation of the answers exceeds <c>Size</c> bytes, - where <c>Size</c> is the value of the <c>size</c> option.</p> + <p>The sorter will use temporary files only if + <c><anno>QH1</anno></c> does not evaluate to a list and the + size of the binary representation of the answers exceeds + <c>Size</c> bytes, where <c>Size</c> is the value of the + <c>size</c> option.</p> + + <p><c>keysort(<anno>KeyPos</anno>, <anno>QH1</anno>)</c> + is equivalent to + <c>keysort(<anno>KeyPos</anno>, <anno>QH1</anno>, [])</c>.</p> </desc> </func> <func> - <name>next_answers(QueryCursor [, NumberOfAnswers]) -> - Answers | Error</name> + <name name="next_answers" arity="1"/> + <name name="next_answers" arity="2"/> <fsummary>Return some or all answers to a query.</fsummary> - <type> - <v>NumberOfAnswers = all_remaining | int() > 0</v> - <v>Error = {error, module(), Reason}</v> - <v>Reason = - as returned by file_sorter(3) -</v> - </type> <desc> <p>Returns some or all of the remaining answers to a query - cursor. Only the owner of <c>Cursor</c> can retrieve - answers.</p> - + cursor. Only the owner of <c><anno>QueryCursor</anno></c> can + retrieve answers.</p> <p>The optional argument <c>NumberOfAnswers</c>determines the maximum number of answers returned. The default value is <c>10</c>. If less than the requested number of answers is @@ -983,21 +949,9 @@ end</pre> </func> <func> - <name>q(QueryListComprehension [, Options]) -> QueryHandle</name> + <name name="q" arity="1"/> + <name name="q" arity="2"/> <fsummary>Return a handle for a query list comprehension.</fsummary> - <type> - <v>QueryListComprehension = - - literal query listcomprehension -</v> - <v>Options = [Option] | Option</v> - <v>Option = {max_lookup, MaxLookup} - | {cache, Cache} | cache - | {join, Join} - | {lookup, Lookup} - | {unique, bool()} | unique</v> - <v>MaxLookup = int() >= 0 | infinity</v> - <v>Join = any | lookup | merge | nested_loop</v> - <v>Lookup = bool() | any</v> - </type> <desc> <p><marker id="q"></marker>Returns a query handle for a query list comprehension. The query list comprehension must be the @@ -1024,7 +978,7 @@ end</pre> <pre> ... -A = [X || {X} <- [{1},{2}]], +A = [X || {X} <- [{1},{2}]], QH = qlc:q(A), ...</pre> @@ -1034,6 +988,9 @@ QH = qlc:q(A), list comprehension"); the shell process stops with a <c>badarg</c> reason.</p> + <p><c>q(<anno>QLC</anno>)</c> is equivalent to + <c>q(<anno>QLC</anno>, [])</c>.</p> + <p>The <c>{cache, ets}</c> option can be used to cache the answers to a query list comprehension. The answers are stored in one ETS table for each cached query list @@ -1092,26 +1049,26 @@ QH = qlc:q(A), <input>io:format("~s~n", [qlc:info(Q)]).</input> begin V1 = - qlc:q([ + qlc:q([ P0 || P0 = {X,Z} <- qlc:keysort(1, [{a,1},{b,4},{c,6}], []) ]), V2 = - qlc:q([ + qlc:q([ P0 || P0 = {W,Y} <- qlc:keysort(2, [{2,a},{3,b},{4,c}], []) ]), V3 = - qlc:q([ + qlc:q([ [G1|G2] || G1 <- V1, G2 <- V2, element(1, G1) == element(2, G2) ], [{join,merge},{cache,list}]), - qlc:q([ + qlc:q([ {A,X,Z,W} || A <- [a,b,c], [{X,Z}|{W,Y}] <- V3, @@ -1170,7 +1127,7 @@ ets:match_spec_run( elements of the key {X, Y} are compared separately.</p> <p>The <c>{lookup, true}</c> option can be used to ensure - that the <c>qlc</c> module will look up constants in some + that the <c>qlc</c> module will look up constants in some QLC table. If there are more than one QLC table among the generators' list expressions, constants have to be looked up in at least one @@ -1190,7 +1147,7 @@ ets:match_spec_run( <c>{join, nested_loop}</c> invokes the method of matching every pair of objects from two handles. The last method is mostly very slow. The evaluation of the query - fails if the <c>qlc</c> module cannot carry out the chosen + fails if the <c>qlc</c> module cannot carry out the chosen join method. The default value is <c>any</c> which means that some fast join method will be used if possible.</p> @@ -1198,47 +1155,33 @@ ets:match_spec_run( </func> <func> - <name>sort(QH1 [, SortOptions]) -> QH2</name> + <name name="sort" arity="1"/> + <name name="sort" arity="2"/> <fsummary>Return a query handle.</fsummary> - <type> - <v>QH1 = QueryHandleOrList</v> - <v>QH2 = QueryHandle</v> - </type> <desc> <p>Returns a query handle. When evaluating the query handle - <c>QH2</c> the answers to the query handle <c>QH1</c> are - sorted by <seealso + <c><anno>QH2</anno></c> the answers to the query handle + <c><anno>QH1</anno></c> are sorted by <seealso marker="file_sorter">file_sorter:sort/3</seealso> according to the options.</p> - <p>The sorter will use temporary files only if <c>QH1</c> does - not evaluate to a list and the size of the binary - representation of the answers exceeds <c>Size</c> bytes, - where <c>Size</c> is the value of the <c>size</c> option.</p> + <p>The sorter will use temporary files only if + <c><anno>QH1</anno></c> does not evaluate to a list and the + size of the binary representation of the answers exceeds + <c>Size</c> bytes, where <c>Size</c> is the value of the + <c>size</c> option.</p> + + <p><c>sort(<anno>QH1</anno>)</c> is equivalent to + <c>sort(<anno>QH1</anno>, [])</c>.</p> + </desc> </func> <func> - <name>string_to_handle(QueryString [, Options [, Bindings]]) -> - QueryHandle | Error</name> + <name name="string_to_handle" arity="1"/> + <name name="string_to_handle" arity="2"/> + <name name="string_to_handle" arity="3"/> <fsummary>Return a handle for a query list comprehension.</fsummary> - <type> - <v>QueryString = string()</v> - <v>Options = [Option] | Option</v> - <v>Option = {max_lookup, MaxLookup} - | {cache, Cache} | cache - | {join, Join} - | {lookup, Lookup} - | {unique, bool()} | unique</v> - <v>MaxLookup = int() >= 0 | infinity</v> - <v>Join = any | lookup | merge | nested_loop</v> - <v>Lookup = bool() | any</v> - <v>Bindings = - as returned by - erl_eval:bindings/1 -</v> - <v>Error = {error, module(), Reason}</v> - <v>Reason = - ErrorInfo as returned by - erl_scan:string/1 or erl_parse:parse_exprs/1 -</v> - </type> <desc> <p>A string version of <c>qlc:q/1,2</c>. When the query handle is evaluated the fun created by the parse transform is @@ -1253,57 +1196,24 @@ ets:match_spec_run( <input>qlc:eval(QH).</input> [2,3,4]</pre> + <p><c>string_to_handle(<anno>QueryString</anno>)</c> + is equivalent to + <c>string_to_handle(<anno>QueryString</anno>, [])</c>.</p> + + <p><c>string_to_handle(<anno>QueryString</anno>, + <anno>Options</anno>)</c> + is equivalent to + <c>string_to_handle(<anno>QueryString</anno>, + <anno>Options</anno>, erl_eval:new_bindings())</c>.</p> + <p>This function is probably useful mostly when called from outside of Erlang, for instance from a driver written in C.</p> </desc> </func> <func> - <name>table(TraverseFun, Options) -> QueryHandle</name> + <name name="table" arity="2"/> <fsummary>Return a query handle for a table.</fsummary> - <type> - <v>TraverseFun = TraverseFun0 | TraverseFun1</v> - <v>TraverseFun0 = fun() -> TraverseResult</v> - <v>TraverseFun1 = fun(MatchExpression) -> TraverseResult</v> - <v>TraverseResult = Objects | term()</v> - <v>Objects = [] | [term() | ObjectList]</v> - <v>ObjectList = TraverseFun0 | Objects</v> - <v>Options = [Option] | Option</v> - <v>Option = {format_fun, FormatFun} - | {info_fun, InfoFun} - | {lookup_fun, LookupFun} - | {parent_fun, ParentFun} - | {post_fun, PostFun} - | {pre_fun, PreFun} - | {key_equality, KeyComparison}</v> - <v>FormatFun = undefined | fun(SelectedObjects) -> FormatedTable</v> - <v>SelectedObjects = all - | {all, NElements, DepthFun} - | {match_spec, MatchExpression} - | {lookup, Position, Keys} - | {lookup, Position, Keys, NElements, DepthFun}</v> - <v>NElements = infinity | int() > 0</v> - <v>DepthFun = fun(term()) -> term()</v> - <v>FormatedTable = {Mod, Fun, Args} - | AbstractExpression - | character_list()</v> - <v>InfoFun = undefined | fun(InfoTag) -> InfoValue</v> - <v>InfoTag = indices | is_unique_objects | keypos | num_of_objects</v> - <v>InfoValue = undefined | term()</v> - <v>LookupFun = undefined | fun(Position, Keys) -> LookupResult</v> - <v>LookupResult = [term()] | term()</v> - <v>ParentFun = undefined | fun() -> ParentFunValue</v> - <v>PostFun = undefined | fun() -> void()</v> - <v>PreFun = undefined | fun([PreArg]) -> void()</v> - <v>PreArg = {parent_value, ParentFunValue} | {stop_fun, StopFun}</v> - <v>ParentFunValue = undefined | term()</v> - <v>StopFun = undefined | fun() -> void()</v> - <v>KeyComparison = '=:=' | '=='</v> - <v>Position = int() > 0</v> - <v>Keys = [term()]</v> - <v>Mod = Fun = atom()</v> - <v>Args = [term()]</v> - </type> <desc> <p><marker id="table"></marker>Returns a query handle for a QLC table. In Erlang/OTP there is support for ETS, Dets and @@ -1315,77 +1225,90 @@ ets:match_spec_run( as well as properties of the table are handled by callback functions provided as options to <c>qlc:table/2</c>.</p> - <p>The callback function <c>TraverseFun</c> is used for - traversing the table. It is to return a list of objects - terminated by either <c>[]</c> or a nullary fun to be used - for traversing the not yet traversed objects of the table. - Any other return value is immediately returned as value of - the query evaluation. Unary <c>TraverseFun</c>s are to - accept a match specification as argument. The match - specification is created by the parse transform by analyzing - the pattern of the generator calling <c>qlc:table/2</c> and - filters using variables introduced in the pattern. If the - parse transform cannot find a match specification equivalent - to the pattern and filters, <c>TraverseFun</c> will be - called with a match specification returning every object. - Modules that can utilize match specifications for optimized + <p>The callback function <c><anno>TraverseFun</anno></c> is + used for traversing the table. It is to return a list of + objects terminated by either <c>[]</c> or a nullary fun to + be used for traversing the not yet traversed objects of the + table. Any other return value is immediately returned as + value of the query evaluation. Unary + <c><anno>TraverseFun</anno></c>s are to accept a match + specification as argument. The match specification is + created by the parse transform by analyzing the pattern of + the generator calling <c>qlc:table/2</c> and filters using + variables introduced in the pattern. If the parse transform + cannot find a match specification equivalent to the pattern + and filters, <c><anno>TraverseFun</anno></c> will be called + with a match specification returning every object. Modules + that can utilize match specifications for optimized traversal of tables should call <c>qlc:table/2</c> with a - unary <c>TraverseFun</c> while other modules can provide a - nullary <c>TraverseFun</c>. <c>ets:table/2</c> is an example - of the former; <c>gb_table:table/1</c> in the <seealso - marker="#implementing_a_qlc_table">Implementing a QLC - table</seealso> section is an example of the latter.</p> - - <p><c>PreFun</c> is a unary callback function that is called - once before the table is read for the first time. If the - call fails, the query evaluation fails. Similarly, the - nullary callback function <c>PostFun</c> is called once - after the table was last read. The return value, which is - caught, is ignored. If <c>PreFun</c> has been called for a - table, <c>PostFun</c> is guaranteed to be called for that - table, even if the evaluation of the query fails for some - reason. The order in which pre (post) functions for + unary + <c><anno>TraverseFun</anno></c> while other modules can + provide a nullary + <c><anno>TraverseFun</anno></c>. <c>ets:table/2</c> is an + example of the former; <c>gb_table:table/1</c> in the + <seealso marker="#implementing_a_qlc_table">Implementing a + QLC table</seealso> section is an example of the latter.</p> + + <p><c><anno>PreFun</anno></c> is a unary callback function + that is called once before the table is read for the first + time. If the call fails, the query evaluation fails. + Similarly, the nullary callback function + <c><anno>PostFun</anno></c> is called once after the table + was last read. The return value, which is caught, is + ignored. If <c><anno>PreFun</anno></c> has been called for a + table, + <c><anno>PostFun</anno></c> is guaranteed to be called for + that table, even if the evaluation of the query fails for + some reason. The order in which pre (post) functions for different tables are evaluated is not specified. Other table - access than reading, such as calling <c>InfoFun</c>, is - assumed to be OK at any time. The argument <c>PreArgs</c> is - a list of tagged values. Currently there are two tags, + access than reading, such as calling + <c><anno>InfoFun</anno></c>, is assumed to be OK at any + time. The argument <c><anno>PreArgs</anno></c> is a list of + tagged values. Currently there are two tags, <c>parent_value</c> and <c>stop_fun</c>, used by Mnesia for managing transactions. The value of <c>parent_value</c> is - the value returned by <c>ParentFun</c>, or <c>undefined</c> - if there is no <c>ParentFun</c>. <c>ParentFun</c> is called - once just before the call of <c>PreFun</c> in the context of - the process calling <c>eval</c>, <c>fold</c>, or + the value returned by <c><anno>ParentFun</anno></c>, or + <c>undefined</c> if there is no <c>ParentFun</c>. + <c><anno>ParentFun</anno></c> is called once just before the + call of + <c><anno>PreFun</anno></c> in the context of the process + calling + <c>eval</c>, <c>fold</c>, or <c>cursor</c>. The value of <c>stop_fun</c> is a nullary fun that deletes the cursor if called from the parent, or <c>undefined</c> if there is no cursor.</p> <p><marker id="lookup_fun"></marker>The binary callback - function <c>LookupFun</c> is used for looking up objects in - the table. The first argument <c>Position</c> is the key - position or an indexed position and the second argument - <c>Keys</c> is a sorted list of unique values. The return - value is to be a list of all objects (tuples) such that the - element at <c>Position</c> is a member of <c>Keys</c>. Any - other return value is immediately returned as value of the - query evaluation. <c>LookupFun</c> is called instead of + function <c><anno>LookupFun</anno></c> is used for looking + up objects in the table. The first argument + <c><anno>Position</anno></c> is the key position or an + indexed position and the second argument + <c><anno>Keys</anno></c> is a sorted list of unique values. + The return value is to be a list of all objects (tuples) + such that the element at <c>Position</c> is a member of + <c><anno>Keys</anno></c>. Any other return value is + immediately returned as value of the query evaluation. + <c><anno>LookupFun</anno></c> is called instead of traversing the table if the parse transform at compile time can find out that the filters match and compare the element - at <c>Position</c> in such a way that only <c>Keys</c> need - to be looked up in order to find all potential answers. The - key position is obtained by calling <c>InfoFun(keypos)</c> - and the indexed positions by calling - <c>InfoFun(indices)</c>. If the key position can be used for - lookup it is always chosen, otherwise the indexed position - requiring the least number of lookups is chosen. If there is - a tie between two indexed positions the one occurring first - in the list returned by <c>InfoFun</c> is chosen. Positions - requiring more than <seealso - marker="#max_lookup">max_lookup</seealso> lookups are - ignored.</p> - - <p>The unary callback function <c>InfoFun</c> is to return - information about the table. <c>undefined</c> should be - returned if the value of some tag is unknown:</p> + at <c><anno>Position</anno></c> in such a way that only + <c><anno>Keys</anno></c> need to be looked up in order to + find all potential answers. The key position is obtained by + calling + <c><anno>InfoFun</anno>(keypos)</c> and the indexed + positions by calling + <c><anno>InfoFun</anno>(indices)</c>. If the key position + can be used for lookup it is always chosen, otherwise the + indexed position requiring the least number of lookups is + chosen. If there is a tie between two indexed positions the + one occurring first in the list returned by + <c><anno>InfoFun</anno></c> is chosen. Positions requiring + more than <seealso marker="#max_lookup">max_lookup</seealso> + lookups are ignored.</p> + + <p>The unary callback function <c><anno>InfoFun</anno></c> is + to return information about the table. <c>undefined</c> + should be returned if the value of some tag is unknown:</p> <list type="bulleted"> <item><c>indices</c>. Returns a list of indexed @@ -1406,20 +1329,22 @@ ets:match_spec_run( </item> </list> - <p>The unary callback function <c>FormatFun</c> is used by - <seealso marker="#info">qlc:info/1,2</seealso> for - displaying the call that created the table's query handle. - The default value, <c>undefined</c>, means that + <p>The unary callback function <c><anno>FormatFun</anno></c> + is used by <seealso marker="#info">qlc:info/1,2</seealso> + for displaying the call that created the table's query + handle. The default value, <c>undefined</c>, means that <c>info/1,2</c> displays a call to <c>'$MOD':'$FUN'/0</c>. - It is up to <c>FormatFun</c> to present the selected objects - of the table in a suitable way. However, if a character list - is chosen for presentation it must be an Erlang expression - that can be scanned and parsed (a trailing dot will be added - by <c>qlc:info</c> though). <c>FormatFun</c> is called with - an argument that describes the selected objects based on - optimizations done as a result of analyzing the filters of - the QLC where the call to <c>qlc:table/2</c> occurs. The - possible values of the argument are:</p> + It is up to <c><anno>FormatFun</anno></c> to present the + selected objects of the table in a suitable way. However, if + a character list is chosen for presentation it must be an + Erlang expression that can be scanned and parsed (a trailing + dot will be added by <c>qlc:info</c> though). + <c><anno>FormatFun</anno></c> is called with an argument + that describes the selected objects based on optimizations + done as a result of analyzing the filters of the QLC where + the call to + <c>qlc:table/2</c> occurs. The possible values of the + argument are:</p> <list type="bulleted"> <item><c>{lookup, Position, Keys, NElements, DepthFun}</c>. @@ -1443,10 +1368,12 @@ ets:match_spec_run( can be used for limiting the size of terms; calling <c>DepthFun(Term)</c> substitutes <c>'...'</c> for parts of <c>Term</c> below the depth specified by the <c>info/1,2</c> - option <c>depth</c>. If calling <c>FormatFun</c> with an - argument including <c>NElements</c> and <c>DepthFun</c> - fails, <c>FormatFun</c> is called once again with an - argument excluding <c>NElements</c> and <c>DepthFun</c> + option <c>depth</c>. If calling + <c><anno>FormatFun</anno></c> with an argument including + <c>NElements</c> and <c>DepthFun</c> fails, + <c><anno>FormatFun</anno></c> is called once again with an + argument excluding + <c>NElements</c> and <c>DepthFun</c> (<c>{lookup, Position, Keys}</c> or <c>all</c>).</p> @@ -1458,7 +1385,7 @@ ets:match_spec_run( <p>See <seealso marker="ets#qlc_table">ets(3)</seealso>, <seealso marker="dets#qlc_table">dets(3)</seealso> and - <seealso marker="mnesia:mnesia#qlc_table">mnesia(3)</seealso> + <seealso marker="mnesia:mnesia#qlc_table">mnesia(3)</seealso> for the various options recognized by <c>table/1,2</c> in respective module.</p> </desc> @@ -1472,12 +1399,12 @@ ets:match_spec_run( <seealso marker="doc/reference_manual:users_guide"> Erlang Reference Manual</seealso>, <seealso marker="erl_eval">erl_eval(3)</seealso>, - <seealso marker="erts:erlang">erlang(3)</seealso>, + <seealso marker="erts:erlang">erlang(3)</seealso>, <seealso marker="ets">ets(3)</seealso>, - <seealso marker="kernel:file">file(3)</seealso>, - <seealso marker="error_logger:file">error_logger(3)</seealso>, + <seealso marker="kernel:file">file(3)</seealso>, + <seealso marker="error_logger:file">error_logger(3)</seealso>, <seealso marker="file_sorter">file_sorter(3)</seealso>, - <seealso marker="mnesia:mnesia">mnesia(3)</seealso>, + <seealso marker="mnesia:mnesia">mnesia(3)</seealso>, <seealso marker="doc/programming_examples:users_guide"> Programming Examples</seealso>, <seealso marker="shell">shell(3)</seealso></p> diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml index 5ada1c2c57..383f52d10d 100644 --- a/lib/stdlib/doc/src/queue.xml +++ b/lib/stdlib/doc/src/queue.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -88,122 +88,94 @@ <title>Original API</title> </section> + <datatypes> + <datatype> + <name><marker id="type-queue">queue()</marker></name> + <desc><p>As returned by <c>new/0</c>.</p></desc> + </datatype> + </datatypes> + <funcs> <func> - <name>new() -> Q</name> + <name name="new" arity="0"/> <fsummary>Create an empty queue</fsummary> - <type> - <v>Q = queue()</v> - </type> <desc> <p>Returns an empty queue.</p> </desc> </func> <func> - <name>is_queue(Term) -> true | false</name> + <name name="is_queue" arity="1"/> <fsummary>Test if a term is a queue</fsummary> - <type> - <v>Term = term()</v> - </type> <desc> - <p>Tests if <c>Q</c> is a queue and returns <c>true</c> if so and + <p>Tests if <c><anno>Term</anno></c> is a queue and returns <c>true</c> if so and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_empty(Q) -> true | false</name> + <name name="is_empty" arity="1"/> <fsummary>Test if a queue is empty</fsummary> - <type> - <v>Q = queue()</v> - </type> <desc> - <p>Tests if <c>Q</c> is empty and returns <c>true</c> if so and + <p>Tests if <c><anno>Q</anno></c> is empty and returns <c>true</c> if so and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>len(Q) -> N</name> + <name name="len" arity="1"/> <fsummary>Get the length of a queue</fsummary> - <type> - <v>Q = queue()</v> - <v>N = integer()</v> - </type> <desc> - <p>Calculates and returns the length of queue <c>Q</c>.</p> + <p>Calculates and returns the length of queue <c><anno>Q</anno></c>.</p> </desc> </func> <func> - <name>in(Item, Q1) -> Q2</name> + <name name="in" arity="2"/> <fsummary>Insert an item at the rear of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Inserts <c>Item</c> at the rear of queue <c>Q1</c>. - Returns the resulting queue <c>Q2</c>.</p> + <p>Inserts <c><anno>Item</anno></c> at the rear of queue <c><anno>Q1</anno></c>. + Returns the resulting queue <c><anno>Q2</anno></c>.</p> </desc> </func> <func> - <name>in_r(Item, Q1) -> Q2</name> + <name name="in_r" arity="2"/> <fsummary>Insert an item at the front of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Inserts <c>Item</c> at the front of queue <c>Q1</c>. - Returns the resulting queue <c>Q2</c>.</p> + <p>Inserts <c><anno>Item</anno></c> at the front of queue <c><anno>Q1</anno></c>. + Returns the resulting queue <c><anno>Q2</anno></c>.</p> </desc> </func> <func> - <name>out(Q1) -> Result</name> + <name name="out" arity="1"/> <fsummary>Remove the front item from a queue</fsummary> - <type> - <v>Result = {{value, Item}, Q2} | {empty, Q1}</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Removes the item at the front of queue <c>Q1</c>. Returns the - tuple <c>{{value, Item}, Q2}</c>, where <c>Item</c> is the - item removed and <c>Q2</c> is the resulting queue. If <c>Q1</c> is - empty, the tuple <c>{empty, Q1}</c> is returned.</p> + <p>Removes the item at the front of queue <c><anno>Q1</anno></c>. Returns the + tuple <c>{{value, <anno>Item</anno>}, <anno>Q2</anno>}</c>, where <c><anno>Item</anno></c> is the + item removed and <c><anno>Q2</anno></c> is the resulting queue. If <c><anno>Q1</anno></c> is + empty, the tuple <c>{empty, <anno>Q1</anno>}</c> is returned.</p> </desc> </func> <func> - <name>out_r(Q1) -> Result</name> + <name name="out_r" arity="1"/> <fsummary>Remove the rear item from a queue</fsummary> - <type> - <v>Result = {{value, Item}, Q2} | {empty, Q1}</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Removes the item at the rear of the queue <c>Q1</c>. Returns the - tuple <c>{{value, Item}, Q2}</c>, where <c>Item</c> is the - item removed and <c>Q2</c> is the new queue. If <c>Q1</c> is - empty, the tuple <c>{empty, Q1}</c> is returned. </p> + <p>Removes the item at the rear of the queue <c><anno>Q1</anno></c>. Returns the + tuple <c>{{value, <anno>Item</anno>}, <anno>Q2</anno>}</c>, where <c><anno>Item</anno></c> is the + item removed and <c><anno>Q2</anno></c> is the new queue. If <c><anno>Q1</anno></c> is + empty, the tuple <c>{empty, <anno>Q1</anno>}</c> is returned. </p> </desc> </func> <func> - <name>from_list(L) -> queue()</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list to a queue</fsummary> - <type> - <v>L = list()</v> - </type> <desc> - <p>Returns a queue containing the items in <c>L</c> in the + <p>Returns a queue containing the items in <c><anno>L</anno></c> in the same order; the head item of the list will become the front item of the queue.</p> </desc> </func> <func> - <name>to_list(Q) -> list()</name> + <name name="to_list" arity="1"/> <fsummary>Convert a queue to a list</fsummary> - <type> - <v>Q = queue()</v> - </type> <desc> <p>Returns a list of the items in the queue in the same order; the front item of the queue will become the head of the list.</p> @@ -211,57 +183,43 @@ </func> <func> - <name>reverse(Q1) -> Q2</name> + <name name="reverse" arity="1"/> <fsummary>Reverse a queue</fsummary> - <type> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that contains the items of - <c>Q1</c> in the reverse order.</p> + <p>Returns a queue <c><anno>Q2</anno></c> that contains the items of + <c><anno>Q1</anno></c> in the reverse order.</p> </desc> </func> <func> - <name>split(N, Q1) -> {Q2,Q3}</name> + <name name="split" arity="2"/> <fsummary>Split a queue in two</fsummary> - <type> - <v>N = integer()</v> - <v>Q1 = Q2 = Q3 = queue()</v> - </type> <desc> - <p>Splits <c>Q1</c> in two. The <c>N</c> front items - are put in <c>Q2</c> and the rest in <c>Q3</c></p> + <p>Splits <c><anno>Q1</anno></c> in two. The <c><anno>N</anno></c> front items + are put in <c><anno>Q2</anno></c> and the rest in <c><anno>Q3</anno></c></p> </desc> </func> <func> - <name>join(Q1, Q2) -> Q3</name> + <name name="join" arity="2"/> <fsummary>Join two queues</fsummary> - <type> - <v>Q1 = Q2 = Q3 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q3</c> that is the result of joining - <c>Q1</c> and <c>Q2</c> with <c>Q1</c> in front of - <c>Q2</c>.</p> + <p>Returns a queue <c><anno>Q3</anno></c> that is the result of joining + <c><anno>Q1</anno></c> and <c><anno>Q2</anno></c> with <c><anno>Q1</anno></c> in front of + <c><anno>Q2</anno></c>.</p> </desc> </func> <func> - <name>filter(Fun, Q1) -> Q2</name> + <name name="filter" arity="2"/> <fsummary>Filter a queue</fsummary> - <type> - <v>Fun = fun(Item) -> bool() | list()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that is the result of calling - <c>Fun(Item)</c> on all items in <c>Q1</c>, + <p>Returns a queue <c><anno>Q2</anno></c> that is the result of calling + <c><anno>Fun</anno>(<anno>Item</anno>)</c> on all items in <c><anno>Q1</anno></c>, in order from front to rear.</p> - <p>If <c>Fun(Item)</c> returns <c>true</c>, <c>Item</c> + <p>If <c><anno>Fun</anno>(<anno>Item</anno>)</c> returns <c>true</c>, <c>Item</c> is copied to the result queue. If it returns <c>false</c>, - <c>Item</c> is not copied. If it returns a list + <c><anno>Item</anno></c> is not copied. If it returns a list the list elements are inserted instead of <c>Item</c> in the result queue.</p> - <p>So, <c>Fun(Item)</c> returning <c>[Item]</c> is thereby + <p>So, <c><anno>Fun</anno>(<anno>Item</anno>)</c> returning <c>[<anno>Item</anno>]</c> is thereby semantically equivalent to returning <c>true</c>, just as returning <c>[]</c> is semantically equivalent to returning <c>false</c>. But returning a list builds @@ -269,15 +227,11 @@ </desc> </func> <func> - <name>member(Item, Q) -> bool()</name> + <name name="member" arity="2"/> <fsummary>Test if an item is in a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Item</c> matches some element - in <c>Q</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Item</anno></c> matches some element + in <c><anno>Q</anno></c>, otherwise <c>false</c>.</p> </desc> </func> </funcs> @@ -290,77 +244,53 @@ <funcs> <func> - <name>get(Q) -> Item</name> + <name name="get" arity="1"/> <fsummary>Return the front item of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns <c>Item</c> at the front of queue <c>Q</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p> + <p>Returns <c><anno>Item</anno></c> at the front of queue <c><anno>Q</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> <func> - <name>get_r(Q) -> Item</name> + <name name="get_r" arity="1"/> <fsummary>Return the rear item of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns <c>Item</c> at the rear of queue <c>Q</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p> + <p>Returns <c><anno>Item</anno></c> at the rear of queue <c><anno>Q</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> <func> - <name>drop(Q1) -> Q2</name> + <name name="drop" arity="1"/> <fsummary>Remove the front item from a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that is the result of removing - the front item from <c>Q1</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing + the front item from <c><anno>Q1</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p> </desc> </func> <func> - <name>drop_r(Q1) -> Q2</name> + <name name="drop_r" arity="1"/> <fsummary>Remove the rear item from a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that is the result of removing - the rear item from <c>Q1</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing + the rear item from <c><anno>Q1</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p> </desc> </func> <func> - <name>peek(Q) -> {value,Item} | empty</name> + <name name="peek" arity="1"/> <fsummary>Return the front item of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns the tuple <c>{value, Item}</c> where <c>Item</c> is the - front item of <c>Q</c>, or <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns the tuple <c>{value, <anno>Item</anno>}</c> where <c><anno>Item</anno></c> is the + front item of <c><anno>Q</anno></c>, or <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> <func> - <name>peek_r(Q) -> {value,Item} | empty</name> + <name name="peek_r" arity="1"/> <fsummary>Return the rear item of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns the tuple <c>{value, Item}</c> where <c>Item</c> is the - rear item of <c>Q</c>, or <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns the tuple <c>{value, <anno>Item</anno>}</c> where <c><anno>Item</anno></c> is the + rear item of <c><anno>Q</anno></c>, or <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> </funcs> @@ -372,80 +302,56 @@ <funcs> <func> - <name>cons(Item, Q1) -> Q2</name> + <name name="cons" arity="2"/> <fsummary>Insert an item at the head of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Inserts <c>Item</c> at the head of queue <c>Q1</c>. Returns - the new queue <c>Q2</c>.</p> + <p>Inserts <c><anno>Item</anno></c> at the head of queue <c><anno>Q1</anno></c>. Returns + the new queue <c><anno>Q2</anno></c>.</p> </desc> </func> <func> - <name>head(Q) -> Item</name> + <name name="head" arity="1"/> <fsummary>Return the item at the head of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns <c>Item</c> from the head of queue <c>Q</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p> + <p>Returns <c><anno>Item</anno></c> from the head of queue <c><anno>Q</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> <func> - <name>tail(Q1) -> Q2</name> + <name name="tail" arity="1"/> <fsummary>Remove the head item from a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that is the result of removing - the head item from <c>Q1</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing + the head item from <c><anno>Q1</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p> </desc> </func> <func> - <name>snoc(Q1, Item) -> Q2</name> + <name name="snoc" arity="2"/> <fsummary>Insert an item at the tail of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Inserts <c>Item</c> as the tail item of queue <c>Q1</c>. Returns - the new queue <c>Q2</c>.</p> + <p>Inserts <c><anno>Item</anno></c> as the tail item of queue <c><anno>Q1</anno></c>. Returns + the new queue <c><anno>Q2</anno></c>.</p> </desc> </func> <func> - <name>daeh(Q) -> Item</name> - <name>last(Q) -> Item</name> + <name name="daeh" arity="1"/> + <name name="last" arity="1"/> <fsummary>Return the tail item of a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q = queue()</v> - </type> <desc> - <p>Returns the tail item of queue <c>Q</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p> + <p>Returns the tail item of queue <c><anno>Q</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p> </desc> </func> <func> - <name>liat(Q1) -> Q2</name> - <name>init(Q1) -> Q2</name> - <name>lait(Q1) -> Q2</name> + <name name="liat" arity="1"/> + <name name="init" arity="1"/> + <name name="lait" arity="1"/> <fsummary>Remove the tail item from a queue</fsummary> - <type> - <v>Item = term()</v> - <v>Q1 = Q2 = queue()</v> - </type> <desc> - <p>Returns a queue <c>Q2</c> that is the result of removing - the tail item from <c>Q1</c>.</p> - <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p> + <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing + the tail item from <c><anno>Q1</anno></c>.</p> + <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p> <p>The name <c>lait/1</c> is a misspelling - do not use it anymore.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml index 26f22db48e..1b8fa44883 100644 --- a/lib/stdlib/doc/src/random.xml +++ b/lib/stdlib/doc/src/random.xml @@ -49,9 +49,15 @@ strong. If a strong cryptographic random number generator is needed for example <c>crypto:rand_bytes/1</c> could be used instead.</p> </description> + <datatypes> + <datatype> + <name name="ran"/> + <desc><p>The state.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>seed() -> ran()</name> + <name name="seed" arity="0"/> <fsummary>Seeds random number generation with default values</fsummary> <desc> <p>Seeds random number generation with default (fixed) values @@ -59,11 +65,8 @@ </desc> </func> <func> - <name>seed(A1, A2, A3) -> undefined | ran()</name> + <name name="seed" arity="3"/> <fsummary>Seeds random number generator</fsummary> - <type> - <v>A1 = A2 = A3 = integer()</v> - </type> <desc> <p>Seeds random number generation with integer values in the process dictionary, and returns the old state.</p> @@ -76,26 +79,23 @@ </desc> </func> <func> - <name>seed({A1, A2, A3}) -> undefined | ran()</name> + <name name="seed" arity="1"/> <fsummary>Seeds random number generator</fsummary> - <type> - <v>A1 = A2 = A3 = integer()</v> - </type> <desc> <p> - <c>seed({A1, A2, A3})</c> is equivalent to <c>seed(A1, A2, A3)</c>. + <c>seed({<anno>A1</anno>, <anno>A2</anno>, <anno>A3</anno>})</c> is equivalent to <c>seed(<anno>A1</anno>, <anno>A2</anno>, <anno>A3</anno>)</c>. </p> </desc> </func> <func> - <name>seed0() -> ran()</name> + <name name="seed0" arity="0"/> <fsummary>Return default state for random number generation</fsummary> <desc> <p>Returns the default state.</p> </desc> </func> <func> - <name>uniform()-> float()</name> + <name name="uniform" arity="0"/> <fsummary>Return a random float</fsummary> <desc> <p>Returns a random float uniformly distributed between <c>0.0</c> @@ -103,39 +103,29 @@ </desc> </func> <func> - <name>uniform(N) -> integer()</name> + <name name="uniform" arity="1"/> <fsummary>Return a random integer</fsummary> - <type> - <v>N = integer()</v> - </type> <desc> - <p>Given an integer <c>N >= 1</c>, <c>uniform/1</c> returns a + <p>Given an integer <c><anno>N</anno> >= 1</c>, <c>uniform/1</c> returns a random integer uniformly distributed between <c>1</c> and - <c>N</c>, updating the state in the process dictionary.</p> + <c><anno>N</anno></c>, updating the state in the process dictionary.</p> </desc> </func> <func> - <name>uniform_s(State0) -> {float(), State1}</name> + <name name="uniform_s" arity="1"/> <fsummary>Return a random float</fsummary> - <type> - <v>State0 = State1 = ran()</v> - </type> <desc> <p>Given a state, <c>uniform_s/1</c>returns a random float uniformly distributed between <c>0.0</c> and <c>1.0</c>, and a new state.</p> </desc> </func> <func> - <name>uniform_s(N, State0) -> {integer(), State1}</name> + <name name="uniform_s" arity="2"/> <fsummary>Return a random integer</fsummary> - <type> - <v>N = integer()</v> - <v>State0 = State1 = ran()</v> - </type> <desc> - <p>Given an integer <c>N >= 1</c> and a state, <c>uniform_s/2</c> + <p>Given an integer <c><anno>N</anno> >= 1</c> and a state, <c>uniform_s/2</c> returns a random integer uniformly distributed between <c>1</c> and - <c>N</c>, and a new state.</p> + <c><anno>N</anno></c>, and a new state.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml index 9091035392..18867cfb68 100644 --- a/lib/stdlib/doc/src/re.xml +++ b/lib/stdlib/doc/src/re.xml @@ -59,28 +59,24 @@ </description> - <section> - <title>DATA TYPES</title> - <code type="none"> - iodata() = iolist() | binary() - iolist() = [char() | binary() | iolist()] - - a binary is allowed as the tail of the list</code> - <code type="none"> - unicode_binary() = binary() with characters encoded in UTF-8 coding standard - unicode_char() = integer() representing a valid unicode codepoint - - chardata() = charlist() | unicode_binary() - - charlist() = [unicode_char() | unicode_binary() | charlist()] - - a unicode_binary is allowed as the tail of the list</code> - - <code type="none"> - mp() = Opaque datatype containing a compiled regular expression. - - The mp() is guaranteed to be a tuple() having the atom + <datatypes> + <datatype> + <name name="mp"/> + <desc> + <p>Opaque datatype containing a compiled regular expression. + The mp() is guaranteed to be a tuple() having the atom 're_pattern' as its first element, to allow for matching in guards. The arity of the tuple() or the content of the other fields - may change in future releases.</code> - </section> + may change in future releases.</p> + </desc> + </datatype> + <datatype> + <name name="nl_spec"/> + </datatype> + <datatype> + <name name="compile_option"/> + </datatype> + </datatypes> <funcs> <func> <name>compile(Regexp) -> {ok, MP} | {error, ErrSpec}</name> @@ -96,14 +92,14 @@ <name>compile(Regexp,Options) -> {ok, MP} | {error, ErrSpec}</name> <fsummary>Compile a regular expression into a match program</fsummary> <type> - <v>Regexp = iodata() | charlist()</v> + <v>Regexp = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v> <v>Options = [ Option ]</v> - <v>Option = unicode | anchored | caseless | dollar_endonly | dotall | extended | firstline | multiline | no_auto_capture | dupnames | ungreedy | {newline, NLSpec}| bsr_anycrlf | bsr_unicode</v> - <v>NLSpec = cr | crlf | lf | anycrlf | any </v> - <v>MP = mp()</v> + <v>Option = <seealso marker="#type-compile_option">compile_option()</seealso></v> + <v>NLSpec = <seealso marker="#type-nl_spec">nl_spec()</seealso></v> + <v>MP = <seealso marker="#type-mp">mp()</seealso></v> <v>ErrSpec = {ErrString, Position}</v> <v>ErrString = string()</v> - <v>Position = int()</v> + <v>Position = non_neg_integer()</v> </type> <desc> <p>This function compiles a regular expression with the syntax @@ -116,7 +112,7 @@ time one wants to match.</p> <p>When the unicode option is given, the regular expression should be given as a valid unicode <c>charlist()</c>, otherwise as any valid <c>iodata()</c>.</p> - <p>The options have the following meanings:</p> + <p><marker id="compile_options"/>The options have the following meanings:</p> <taglist> <tag><c>unicode</c></tag> <item>The regular expression is given as a unicode <c>charlist()</c> and the resulting regular expression code is to be run against a valid unicode <c>charlist()</c> subject.</item> @@ -137,7 +133,7 @@ This option makes it possible to include comments inside complicated patterns. N <tag><c>multiline</c></tag> <item><p>By default, PCRE treats the subject string as consisting of a single line of characters (even if it actually contains newlines). The "start of line" metacharacter (^) matches only at the start of the string, while the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (unless <c>dollar_endonly</c> is given). This is the same as Perl.</p> -<p>When <c>multiline</c> it is given, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting <c>multiline</c> has no effect.</p> </item> +<p>When <c>multiline</c> is given, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting <c>multiline</c> has no effect.</p> </item> <tag><c>no_auto_capture</c></tag> <item>Disables the use of numbered capturing parentheses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl. </item> @@ -173,10 +169,10 @@ This option makes it possible to include comments inside complicated patterns. N <name>run(Subject,RE) -> {match, Captured} | nomatch</name> <fsummary>Match a subject against regular expression and capture subpatterns</fsummary> <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata() | charlist()</v> + <v>Subject = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v> + <v>RE = <seealso marker="#type-mp">mp()</seealso> | iodata()</v> <v>Captured = [ CaptureData ]</v> - <v>CaptureData = {int(),int()}</v> + <v>CaptureData = {integer(),integer()}</v> </type> <desc> <p>The same as <c>run(Subject,RE,[])</c>.</p> @@ -186,18 +182,19 @@ This option makes it possible to include comments inside complicated patterns. N <name>run(Subject,RE,Options) -> {match, Captured} | match | nomatch</name> <fsummary>Match a subject against regular expression and capture subpatterns</fsummary> <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata() | charlist()</v> + <v>Subject = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v> + <v>RE = <seealso marker="#type-mp">mp()</seealso> | iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v> <v>Options = [ Option ]</v> - <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {capture, ValueSpec} | {capture, ValueSpec, Type} | CompileOpt</v> + <v>Option = anchored | global | notbol | noteol | notempty | {offset, integer() >= 0} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {capture, ValueSpec} | {capture, ValueSpec, Type} | CompileOpt</v> <v>Type = index | list | binary</v> <v>ValueSpec = all | all_but_first | first | none | ValueList</v> <v>ValueList = [ ValueID ]</v> - <v>ValueID = int() | string() | atom()</v> - <v>CompileOpt = see compile/2 above</v> - <v>NLSpec = cr | crlf | lf | anycrlf | any</v> + <v>ValueID = integer() | string() | atom()</v> + <v>CompileOpt = <seealso marker="#type-compile_option">compile_option()</seealso></v> + <d>See <seealso marker="#compile_options">compile/2</seealso> above.</d> + <v>NLSpec = <seealso marker="#type-nl_spec">nl_spec()</seealso></v> <v>Captured = [ CaptureData ] | [ [ CaptureData ] ... ]</v> - <v>CaptureData = {int(),int()} | ListConversionData | binary()</v> + <v>CaptureData = {integer(),integer()} | ListConversionData | binary()</v> <v>ListConversionData = string() | {error, string(), binary()} | {incomplete, string(), binary()}</v> </type> <desc> @@ -217,7 +214,7 @@ This option makes it possible to include comments inside complicated patterns. N <p>If the regular expression is previously compiled, the option list can only contain the options <c>anchored</c>, <c>global</c>, <c>notbol</c>, <c>noteol</c>, - <c>notempty</c>, <c>{offset, int()}</c>, <c>{newline, + <c>notempty</c>, <c>{offset, integer() >= 0}</c>, <c>{newline, NLSpec}</c> and <c>{capture, ValueSpec}/{capture, ValueSpec, Type}</c>. Otherwise all options valid for the <c>re:compile/2</c> function are allowed as well. Options @@ -360,7 +357,7 @@ This option makes it possible to include comments inside complicated patterns. N behavior of the dollar metacharacter. It does not affect \Z or \z.</item> - <tag><c>{offset, int()}</c></tag> + <tag><c>{offset, integer() >= 0}</c></tag> <item>Start matching at the offset (position) given in the subject string. The offset is zero-based, so that the default is @@ -503,42 +500,27 @@ This option makes it possible to include comments inside complicated patterns. N </desc> </func> <func> - <name>replace(Subject,RE,Replacement) -> iodata() | charlist()</name> + <name name="replace" arity="3"/> <fsummary>Match a subject against regular expression and replace matching elements with Replacement</fsummary> - <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata()</v> - <v>Replacement = iodata() | charlist()</v> - </type> <desc> - <p>The same as <c>replace(Subject,RE,Replacement,[])</c>.</p> + <p>The same as <c>replace(<anno>Subject</anno>,<anno>RE</anno>,<anno>Replacement</anno>,[])</c>.</p> </desc> </func> <func> - <name>replace(Subject,RE,Replacement,Options) -> iodata() | charlist() | binary() | list()</name> + <name name="replace" arity="4"/> <fsummary>Match a subject against regular expression and replace matching elements with Replacement</fsummary> - <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata() | charlist()</v> - <v>Replacement = iodata() | charlist()</v> - <v>Options = [ Option ]</v> - <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {return, ReturnType} | CompileOpt</v> - <v>ReturnType = iodata | list | binary</v> - <v>CompileOpt = see compile/2 above</v> - <v>NLSpec = cr | crlf | lf | anycrlf | any </v> - </type> <desc> - <p>Replaces the matched part of the <c>Subject</c> string with the contents of <c>Replacement</c>.</p> + <p>Replaces the matched part of the <c><anno>Subject</anno></c> string with the contents of <c><anno>Replacement</anno></c>.</p> <p>The permissible options are the same as for <c>re:run/3</c>, except that the <c>capture</c> option is not allowed. - Instead a <c>{return, ReturnType}</c> is present. The default return type is <c>iodata</c>, constructed in a + Instead a <c>{return, <anno>ReturnType</anno>}</c> is present. The default return type is <c>iodata</c>, constructed in a way to minimize copying. The <c>iodata</c> result can be used directly in many i/o-operations. If a flat <c>list()</c> is desired, specify <c>{return, list}</c> and if a binary is preferred, specify <c>{return, binary}</c>.</p> <p>As in the <c>re:run/3</c> function, an <c>mp()</c> compiled - with the <c>unicode</c> option requires the <c>Subject</c> to be + with the <c>unicode</c> option requires the <c><anno>Subject</anno></c> to be a Unicode <c>charlist()</c>. If compilation is done implicitly and the <c>unicode</c> compilation option is given to this - function, both the regular expression and the <c>Subject</c> + function, both the regular expression and the <c><anno>Subject</anno></c> should be given as valid Unicode <c>charlist()</c>s.</p> <p>The replacement string can contain the special character @@ -565,34 +547,17 @@ This option makes it possible to include comments inside complicated patterns. N </desc> </func> <func> - <name>split(Subject,RE) -> SplitList</name> + <name name="split" arity="2"/> <fsummary>Split a string by tokens specified as a regular expression</fsummary> - <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata()</v> - <v>SplitList = [ iodata() | charlist() ]</v> - </type> <desc> - <p>The same as <c>split(Subject,RE,[])</c>.</p> + <p>The same as <c>split(<anno>Subject</anno>,<anno>RE</anno>,[])</c>.</p> </desc> </func> <func> - <name>split(Subject,RE,Options) -> SplitList</name> + <name name="split" arity="3"/> <fsummary>Split a string by tokens specified as a regular expression</fsummary> - <type> - <v>Subject = iodata() | charlist()</v> - <v>RE = mp() | iodata() | charlist()</v> - <v>Options = [ Option ]</v> - <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {return, ReturnType} | {parts, NumParts} | group | trim | CompileOpt</v> - <v>NumParts = int() | infinity</v> - <v>ReturnType = iodata | list | binary</v> - <v>CompileOpt = see compile/2 above</v> - <v>NLSpec = cr | crlf | lf | anycrlf | any </v> - <v>SplitList = [ RetData ] | [ GroupedRetData ]</v> - <v>GroupedRetData = [ RetData ]</v> - <v>RetData = iodata() | charlist() | binary() | list()</v> - </type> + <type_desc variable="CompileOpt">See <seealso marker="#compile_options">compile/2</seealso> above.</type_desc> <desc> <p>This function splits the input into parts by finding tokens according to the regular expression supplied.</p> @@ -602,10 +567,10 @@ This option makes it possible to include comments inside complicated patterns. N of the string is removed from the output.</p> <p>As in the <c>re:run/3</c> function, an <c>mp()</c> compiled - with the <c>unicode</c> option requires the <c>Subject</c> to be + with the <c>unicode</c> option requires the <c><anno>Subject</anno></c> to be a Unicode <c>charlist()</c>. If compilation is done implicitly and the <c>unicode</c> compilation option is given to this - function, both the regular expression and the <c>Subject</c> + function, both the regular expression and the <c><anno>Subject</anno></c> should be given as valid Unicode <c>charlist()</c>s.</p> <p>The result is given as a list of "strings", the @@ -722,7 +687,7 @@ This option makes it possible to include comments inside complicated patterns. N <p>Summary of options not previously described for the <c>re:run/3</c> function:</p> <taglist> - <tag>{return,ReturnType}</tag> + <tag>{return,<anno>ReturnType</anno>}</tag> <item><p>Specifies how the parts of the original string are presented in the result list. The possible types are:</p> <taglist> <tag>iodata</tag> diff --git a/lib/stdlib/doc/src/regexp.xml b/lib/stdlib/doc/src/regexp.xml index 8c4191c88f..35d8e1c3f8 100644 --- a/lib/stdlib/doc/src/regexp.xml +++ b/lib/stdlib/doc/src/regexp.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -40,176 +40,150 @@ <p>This module contains functions for regular expression matching and substitution.</p> </description> + <datatypes> + <datatype> + <name name="errordesc"></name> + </datatype> + <datatype> + <name name="regexp"></name> + <desc><p>Internal representation of a regular expression.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>match(String, RegExp) -> MatchRes</name> + <name name="match" arity="2"/> <fsummary>Match a regular expression</fsummary> - <type> - <v>String = RegExp = string()</v> - <v>MatchRes = {match,Start,Length} | nomatch | {error,errordesc()}</v> - <v>Start = Length = integer()</v> - </type> <desc> - <p>Finds the first, longest match of the regular expression <c>RegExp</c> in <c>String</c>. This function searches for the longest possible match and returns the first one found if there are several expressions of the same length. It returns as follows:</p> + <p>Finds the first, longest match of the regular expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>. This function searches for the longest possible match and returns the first one found if there are several expressions of the same length. It returns as follows:</p> <taglist> - <tag><c>{match,Start,Length}</c></tag> + <tag><c>{match,<anno>Start</anno>,<anno>Length</anno>}</c></tag> <item> - <p>if the match succeeded. <c>Start</c> is the starting - position of the match, and <c>Length</c> is the length of + <p>if the match succeeded. <c><anno>Start</anno></c> is the starting + position of the match, and <c><anno>Length</anno></c> is the length of the matching string.</p> </item> <tag><c>nomatch</c></tag> <item> <p>if there were no matching characters.</p> </item> - <tag><c>{error,Error}</c></tag> + <tag><c>{error,<anno>Error</anno>}</c></tag> <item> - <p>if there was an error in <c>RegExp</c>.</p> + <p>if there was an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>first_match(String, RegExp) -> MatchRes</name> + <name name="first_match" arity="2"/> <fsummary>Match a regular expression</fsummary> - <type> - <v>String = RegExp = string()</v> - <v>MatchRes = {match,Start,Length} | nomatch | {error,errordesc()}</v> - <v>Start = Length = integer()</v> - </type> <desc> - <p>Finds the first match of the regular expression <c>RegExp</c> in <c>String</c>. This call is + <p>Finds the first match of the regular expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>. This call is usually faster than <c>match</c> and it is also a useful way to ascertain that a match exists. It returns as follows:</p> <taglist> - <tag><c>{match,Start,Length}</c></tag> + <tag><c>{match,<anno>Start</anno>,<anno>Length</anno>}</c></tag> <item> - <p>if the match succeeded. <c>Start</c> is the starting - position of the match and <c>Length</c> is the length of + <p>if the match succeeded. <c><anno>Start</anno></c> is the starting + position of the match and <c><anno>Length</anno></c> is the length of the matching string.</p> </item> <tag><c>nomatch</c></tag> <item> <p>if there were no matching characters.</p> </item> - <tag><c>{error,Error}</c></tag> + <tag><c>{error,<anno>Error</anno>}</c></tag> <item> - <p>if there was an error in <c>RegExp</c>.</p> + <p>if there was an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>matches(String, RegExp) -> MatchRes</name> + <name name="matches" arity="2"/> <fsummary>Match a regular expression</fsummary> - <type> - <v>String = RegExp = string()</v> - <v>MatchRes = {match, Matches} | {error, errordesc()}</v> - <v>Matches = list()</v> - </type> <desc> <p>Finds all non-overlapping matches of the - expression <c>RegExp</c> in <c>String</c>. + expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>. It returns as follows:</p> <taglist> - <tag><c>{match, Matches}</c></tag> + <tag><c>{match, <anno>Matches</anno>}</c></tag> <item> <p>if the regular expression was correct. - The list will be empty if there was no match. Each element in the list looks like <c>{Start, Length}</c>, where <c>Start</c> is the starting position of the match, and <c>Length</c> is the length of the matching string.</p> + The list will be empty if there was no match. Each element in the list looks like <c>{<anno>Start</anno>, <anno>Length</anno>}</c>, where <c><anno>Start</anno></c> is the starting position of the match, and <c><anno>Length</anno></c> is the length of the matching string.</p> </item> - <tag><c>{error,Error}</c></tag> + <tag><c>{error,<anno>Error</anno>}</c></tag> <item> - <p>if there was an error in <c>RegExp</c>.</p> + <p>if there was an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>sub(String, RegExp, New) -> SubRes</name> + <name name="sub" arity="3"/> <fsummary>Substitute the first occurrence of a regular expression</fsummary> - <type> - <v>String = RegExp = New = string()</v> - <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v> - <v>RepCount = integer()</v> - </type> <desc> - <p>Substitutes the first occurrence of a substring matching <c>RegExp</c> in <c>String</c> with the string <c>New</c>. A <c><![CDATA[&]]></c> in the string <c>New</c> is replaced by the matched substring of <c>String</c>. <c><![CDATA[\&]]></c> puts a literal <c><![CDATA[&]]></c> into the replacement string. It returns as follows:</p> + <p>Substitutes the first occurrence of a substring matching <c><anno>RegExp</anno></c> in <c><anno>String</anno></c> with the string <c><anno>New</anno></c>. A <c><![CDATA[&]]></c> in the string <c><anno>New</anno></c> is replaced by the matched substring of <c><anno>String</anno></c>. <c><![CDATA[\&]]></c> puts a literal <c><![CDATA[&]]></c> into the replacement string. It returns as follows:</p> <taglist> - <tag><c>{ok,NewString,RepCount}</c></tag> + <tag><c>{ok,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag> <item> - <p>if <c>RegExp</c> is correct. <c>RepCount</c> is the number of replacements which have been made + <p>if <c><anno>RegExp</anno></c> is correct. <c><anno>RepCount</anno></c> is the number of replacements which have been made (this will be either 0 or 1).</p> </item> - <tag><c>{error, Error}</c></tag> + <tag><c>{error, <anno>Error</anno>}</c></tag> <item> - <p>if there is an error in <c>RegExp</c>.</p> + <p>if there is an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>gsub(String, RegExp, New) -> SubRes</name> + <name name="gsub" arity="3"/> <fsummary>Substitute all occurrences of a regular expression</fsummary> - <type> - <v>String = RegExp = New = string()</v> - <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v> - <v>RepCount = integer()</v> - </type> <desc> <p>The same as <c>sub</c>, except that all non-overlapping occurrences of a substring matching - <c>RegExp</c> in <c>String</c> are replaced by the string <c>New</c>. It returns:</p> + <c><anno>RegExp</anno></c> in <c><anno>String</anno></c> are replaced by the string <c><anno>New</anno></c>. It returns:</p> <taglist> - <tag><c>{ok,NewString,RepCount}</c></tag> + <tag><c>{ok,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag> <item> - <p>if <c>RegExp</c> is correct. <c>RepCount</c> is the number of replacements which have been made.</p> + <p>if <c><anno>RegExp</anno></c> is correct. <c><anno>RepCount</anno></c> is the number of replacements which have been made.</p> </item> - <tag><c>{error, Error}</c></tag> + <tag><c>{error, <anno>Error</anno>}</c></tag> <item> - <p>if there is an error in <c>RegExp</c>.</p> + <p>if there is an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>split(String, RegExp) -> SplitRes</name> + <name name="split" arity="2"/> <fsummary>Split a string into fields</fsummary> - <type> - <v>String = RegExp = string()</v> - <v>SubRes = {ok,FieldList} | {error,errordesc()}</v> - <v>Fieldlist = [string()]</v> - </type> <desc> - <p><c>String</c> is split into fields (sub-strings) by the - regular expression <c>RegExp</c>.</p> + <p><c><anno>String</anno></c> is split into fields (sub-strings) by the + regular expression <c><anno>RegExp</anno></c>.</p> <p>If the separator expression is <c>" "</c> (a single space), then the fields are separated by blanks and/or tabs and leading and trailing blanks and tabs are discarded. For all other values of the separator, leading and trailing blanks and tabs are not discarded. It returns:</p> <taglist> - <tag><c>{ok, FieldList}</c></tag> + <tag><c>{ok, <anno>FieldList</anno>}</c></tag> <item> <p>to indicate that the string has been split up into the fields of - <c>FieldList</c>.</p> + <c><anno>FieldList</anno></c>.</p> </item> - <tag><c>{error, Error}</c></tag> + <tag><c>{error, <anno>Error</anno>}</c></tag> <item> - <p>if there is an error in <c>RegExp</c>.</p> + <p>if there is an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>sh_to_awk(ShRegExp) -> AwkRegExp</name> + <name name="sh_to_awk" arity="1"/> <fsummary>Convert an <c>sh</c>regular expression into an <c>AWK</c>one</fsummary> - <type> - <v>ShRegExp AwkRegExp = string()</v> - <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v> - <v>RepCount = integer()</v> - </type> <desc> <p>Converts the <c>sh</c> type regular expression - <c>ShRegExp</c> into a full <c>AWK</c> regular + <c><anno>ShRegExp</anno></c> into a full <c>AWK</c> regular expression. Returns the converted regular expression string. <c>sh</c> expressions are used in the shell for matching file names and have the following special @@ -236,40 +210,32 @@ </desc> </func> <func> - <name>parse(RegExp) -> ParseRes</name> + <name name="parse" arity="1"/> <fsummary>Parse a regular expression</fsummary> - <type> - <v>RegExp = string()</v> - <v>ParseRes = {ok,RE} | {error,errordesc()}</v> - </type> <desc> - <p>Parses the regular expression <c>RegExp</c> and builds the + <p>Parses the regular expression <c><anno>RegExp</anno></c> and builds the internal representation used in the other regular expression functions. Such representations can be used in all of the other functions instead of a regular expression string. This is more efficient when the same regular expression is used in many strings. It returns:</p> <taglist> - <tag><c>{ok, RE}</c>if <c>RegExp</c>is correct and <c>RE</c>is the internal representation.</tag> + <tag><c>{ok, <anno>RE</anno>}</c></tag> <item> - <p></p> + <p>if <c>RegExp</c> is correct and <c><anno>RE</anno></c> is the internal representation.</p> </item> - <tag><c>{error, Error}</c>if there is an error in <c>RegExpString</c>.</tag> + <tag><c>{error, <anno>Error</anno>}</c></tag> <item> - <p></p> + <p>if there is an error in <c><anno>RegExp</anno></c>.</p> </item> </taglist> </desc> </func> <func> - <name>format_error(ErrorDescriptor) -> Chars</name> + <name name="format_error" arity="1"/> <fsummary>Format an error descriptor</fsummary> - <type> - <v>ErrorDescriptor = errordesc()</v> - <v>Chars = [char() | Chars]</v> - </type> <desc> - <p>Returns a string which describes the error <c>ErrorDescriptor</c> + <p>Returns a string which describes the error <c><anno>ErrorDescriptor</anno></c> returned when there is an error in a regular expression.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml index 3610bb0184..071ee437cb 100644 --- a/lib/stdlib/doc/src/sets.xml +++ b/lib/stdlib/doc/src/sets.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2009</year> + <year>2000</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -43,202 +43,141 @@ different if and only if they do not compare equal (<c>==</c>).</p> </description> - <section> - <title>DATA TYPES</title> - <code type="none"> -set() - as returned by new/0</code> - </section> + <datatypes> + <datatype> + <name><marker id="type-dict">set()</marker></name> + <desc><p>As returned by <c>new/0</c>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>new() -> Set</name> + <name name="new" arity="0"/> <fsummary>Return an empty set</fsummary> - <type> - <v>Set = set()</v> - </type> <desc> <p>Returns a new empty set.</p> </desc> </func> <func> - <name>is_set(Set) -> bool()</name> + <name name="is_set" arity="1"/> <fsummary>Test for an <c>Set</c></fsummary> - <type> - <v>Set = term()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Set</c> is a set of + <p>Returns <c>true</c> if <c><anno>Set</anno></c> is a set of elements, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>size(Set) -> int()</name> + <name name="size" arity="1"/> <fsummary>Return the number of elements in a set</fsummary> - <type> - <v>Set = term()</v> - </type> <desc> - <p>Returns the number of elements in <c>Set</c>.</p> + <p>Returns the number of elements in <c><anno>Set</anno></c>.</p> </desc> </func> <func> - <name>to_list(Set) -> List</name> + <name name="to_list" arity="1"/> <fsummary>Convert an <c>Set</c>into a list</fsummary> - <type> - <v>Set = set()</v> - <v>List = [term()]</v> - </type> <desc> - <p>Returns the elements of <c>Set</c> as a list.</p> + <p>Returns the elements of <c><anno>Set</anno></c> as a list.</p> </desc> </func> <func> - <name>from_list(List) -> Set</name> + <name name="from_list" arity="1"/> <fsummary>Convert a list into an <c>Set</c></fsummary> - <type> - <v>List = [term()]</v> - <v>Set = set()</v> - </type> <desc> - <p>Returns an set of the elements in <c>List</c>.</p> + <p>Returns an set of the elements in <c><anno>List</anno></c>.</p> </desc> </func> <func> - <name>is_element(Element, Set) -> bool()</name> + <name name="is_element" arity="2"/> <fsummary>Test for membership of an <c>Set</c></fsummary> - <type> - <v>Element = term()</v> - <v>Set = set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Element</c> is an element of - <c>Set</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of + <c><anno>Set</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>add_element(Element, Set1) -> Set2</name> + <name name="add_element" arity="2"/> <fsummary>Add an element to an <c>Set</c></fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns a new set formed from <c>Set1</c> with - <c>Element</c> inserted.</p> + <p>Returns a new set formed from <c><anno>Set1</anno></c> with + <c><anno>Element</anno></c> inserted.</p> </desc> </func> <func> - <name>del_element(Element, Set1) -> Set2</name> + <name name="del_element" arity="2"/> <fsummary>Remove an element from an <c>Set</c></fsummary> - <type> - <v>Element = term()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns <c>Set1</c>, but with <c>Element</c> removed.</p> + <p>Returns <c><anno>Set1</anno></c>, but with <c><anno>Element</anno></c> removed.</p> </desc> </func> <func> - <name>union(Set1, Set2) -> Set3</name> + <name name="union" arity="2"/> <fsummary>Return the union of two <c>Sets</c></fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> - <p>Returns the merged (union) set of <c>Set1</c> and - <c>Set2</c>.</p> + <p>Returns the merged (union) set of <c><anno>Set1</anno></c> and + <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>union(SetList) -> Set</name> + <name name="union" arity="1"/> <fsummary>Return the union of a list of <c>Sets</c></fsummary> - <type> - <v>SetList = [set()]</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the merged (union) set of the list of sets.</p> </desc> </func> <func> - <name>intersection(Set1, Set2) -> Set3</name> + <name name="intersection" arity="2"/> <fsummary>Return the intersection of two <c>Sets</c></fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> - <p>Returns the intersection of <c>Set1</c> and - <c>Set2</c>.</p> + <p>Returns the intersection of <c><anno>Set1</anno></c> and + <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>intersection(SetList) -> Set</name> + <name name="intersection" arity="1"/> <fsummary>Return the intersection of a list of <c>Sets</c></fsummary> - <type> - <v>SetList = [set()]</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the intersection of the non-empty list of sets.</p> </desc> </func> <func> - <name>is_disjoint(Set1, Set2) -> bool()</name> + <name name="is_disjoint" arity="2"/> <fsummary>Check whether two <c>Sets</c> are disjoint</fsummary> - <type> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns <c>true</c> if <c>Set1</c> and - <c>Set2</c> are disjoint (have no elements in common), + <p>Returns <c>true</c> if <c><anno>Set1</anno></c> and + <c><anno>Set2</anno></c> are disjoint (have no elements in common), and <c>false</c> otherwise.</p> </desc> </func> <func> - <name>subtract(Set1, Set2) -> Set3</name> + <name name="subtract" arity="2"/> <fsummary>Return the difference of two <c>Sets</c></fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> - <p>Returns only the elements of <c>Set1</c> which are not - also elements of <c>Set2</c>.</p> + <p>Returns only the elements of <c><anno>Set1</anno></c> which are not + also elements of <c><anno>Set2</anno></c>.</p> </desc> </func> <func> - <name>is_subset(Set1, Set2) -> bool()</name> + <name name="is_subset" arity="2"/> <fsummary>Test for subset</fsummary> - <type> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns <c>true</c> when every element of <c>Set</c>1 is - also a member of <c>Set2</c>, otherwise <c>false</c>.</p> + <p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c>1 is + also a member of <c><anno>Set2</anno></c>, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>fold(Function, Acc0, Set) -> Acc1</name> + <name name="fold" arity="3"/> <fsummary>Fold over set elements</fsummary> - <type> - <v>Function = fun (E, AccIn) -> AccOut</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Set = set()</v> - </type> <desc> - <p>Fold <c>Function</c> over every element in <c>Set</c> + <p>Fold <c><anno>Function</anno></c> over every element in <c><anno>Set</anno></c> returning the final value of the accumulator.</p> </desc> </func> <func> - <name>filter(Pred, Set1) -> Set2</name> + <name name="filter" arity="2"/> <fsummary>Filter set elements</fsummary> - <type> - <v>Pred = fun (E) -> bool()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Filter elements in <c>Set1</c> with boolean function - <c>Fun</c>.</p> + <p>Filter elements in <c><anno>Set1</anno></c> with boolean function + <c><anno>Pred</anno></c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml index 73cc1b33bd..bc2120c37d 100644 --- a/lib/stdlib/doc/src/shell.xml +++ b/lib/stdlib/doc/src/shell.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -763,26 +763,20 @@ loop(N) -> <funcs> <func> - <name>history(N) -> integer()</name> + <name name="history" arity="1"/> <fsummary>Sets the number of previous commands to keep</fsummary> - <type> - <v>N = integer()</v> - </type> <desc> <p>Sets the number of previous commands to keep in the - history list to <c>N</c>. The previous number is returned. + history list to <c><anno>N</anno></c>. The previous number is returned. The default number is 20.</p> </desc> </func> <func> - <name>results(N) -> integer()</name> + <name name="results" arity="1"/> <fsummary>Sets the number of previous results to keep</fsummary> - <type> - <v>N = integer()</v> - </type> <desc> <p>Sets the number of results from previous commands to keep in - the history list to <c>N</c>. The previous number is returned. + the history list to <c><anno>N</anno></c>. The previous number is returned. The default number is 20.</p> </desc> </func> @@ -790,7 +784,7 @@ loop(N) -> <name>catch_exception(Bool) -> Bool</name> <fsummary>Sets the exception handling of the shell</fsummary> <type> - <v>Bool = bool()</v> + <v>Bool = boolean()</v> </type> <desc> <p>Sets the exception handling of the evaluator process. The @@ -804,38 +798,29 @@ loop(N) -> </desc> </func> <func> - <name>prompt_func(PromptFunc) -> prompt_func()</name> + <name name="prompt_func" arity="1"/> <fsummary>Sets the shell prompt</fsummary> - <type> - <v>PromptFunc = prompt_func()</v> - <v>prompt_func() = default | {Mod, Func}</v> - <v>Mod = Func = atom()</v> - </type> <desc> <p>Sets the shell prompt function to <c>PromptFunc</c>. The previous prompt function is returned.</p> </desc> </func> <func> - <name>start_restricted(Module) -> ok | {error, Reason}</name> + <name name="start_restricted" arity="1"/> <fsummary>Exits a normal shell and starts a restricted shell.</fsummary> - <type> - <v>Module = atom()</v> - <v>Reason = atom()</v> - </type> <desc> <p>Exits a normal shell and starts a restricted - shell. <c>Module</c> specifies the callback module for the + shell. <c><anno>Module</anno></c> specifies the callback module for the functions <c>local_allowed/3</c> and <c>non_local_allowed/3</c>. The function is meant to be called from the shell.</p> <p>If the callback module cannot be loaded, an error tuple is - returned. The <c>Reason</c> in the error tuple is the one + returned. The <c><anno>Reason</anno></c> in the error tuple is the one returned by the code loader when trying to load the code of the callback module.</p> </desc> </func> <func> - <name>stop_restricted() -> ok</name> + <name name="stop_restricted" arity="0"/> <fsummary>Exits a restricted shell and starts a normal shell.</fsummary> <desc> <p>Exits a restricted shell and starts a normal shell. The function diff --git a/lib/stdlib/doc/src/slave.xml b/lib/stdlib/doc/src/slave.xml index 168d83f301..15b6711731 100644 --- a/lib/stdlib/doc/src/slave.xml +++ b/lib/stdlib/doc/src/slave.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -56,22 +56,16 @@ </description> <funcs> <func> - <name>start(Host) -></name> - <name>start(Host, Name) -></name> - <name>start(Host, Name, Args) -> {ok, Node} | {error, Reason}</name> + <name name="start" arity="1"/> + <name name="start" arity="2"/> + <name name="start" arity="3"/> <fsummary>Start a slave node on a host</fsummary> - <type> - <v>Host = Name = atom()</v> - <v>Args = string()</v> - <v>Node = node()</v> - <v>Reason = timeout | no_rsh | {already_running, Node}</v> - </type> <desc> - <p>Starts a slave node on the host <c>Host</c>. Host names need + <p>Starts a slave node on the host <c><anno>Host</anno></c>. Host names need not necessarily be specified as fully qualified names; short names can also be used. This is the same condition that applies to names of distributed Erlang nodes.</p> - <p>The name of the started node will be <c>Name@Host</c>. If no + <p>The name of the started node will be <c><anno>Name</anno>@<anno>Host</anno></c>. If no name is provided, the name will be the same as the node which executes the call (with the exception of the host name part of the node name).</p> @@ -79,7 +73,7 @@ terminal I/O which is produced at the slave is automatically relayed to the master. Also, the file process will be relayed to the master.</p> - <p>The <c>Args</c> argument is used to set <c>erl</c> command + <p>The <c><anno>Args</anno></c> argument is used to set <c>erl</c> command line arguments. If provided, it is passed to the new node and can be used for a variety of purposes. See <seealso marker="erts:erl#erl">erl(1)</seealso></p> @@ -103,9 +97,9 @@ E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ", Arg = "-mnesia_dir " ++ M ++ " -pa " ++ Dir ++ E, slave:start(H, Name, Arg).</code> - <p>If successful, the function returns <c>{ok, Node}</c>, - where <c>Node</c> is the name of the new node. Otherwise it - returns <c>{error, Reason}</c>, where <c>Reason</c> can be + <p>If successful, the function returns <c>{ok, <anno>Node</anno>}</c>, + where <c><anno>Node</anno></c> is the name of the new node. Otherwise it + returns <c>{error, <anno>Reason</anno>}</c>, where <c><anno>Reason</anno></c> can be one of:</p> <taglist> <tag><c>timeout</c></tag> @@ -123,24 +117,18 @@ slave:start(H, Name, Arg).</code> <item> <p>There is no <c>rsh</c> program on the computer.</p> </item> - <tag><c>{already_running, Node}</c></tag> + <tag><c>{already_running, <anno>Node</anno>}</c></tag> <item> - <p>A node with the name <c>Name@Host</c> already exists.</p> + <p>A node with the name <c><anno>Name</anno>@<anno>Host</anno></c> already exists.</p> </item> </taglist> </desc> </func> <func> - <name>start_link(Host) -></name> - <name>start_link(Host, Name) -></name> - <name>start_link(Host, Name, Args) -> {ok, Node} | {error, Reason}</name> + <name name="start_link" arity="1"/> + <name name="start_link" arity="2"/> + <name name="start_link" arity="3"/> <fsummary>Start and link to a slave node on a host</fsummary> - <type> - <v>Host = Name = atom()</v> - <v>Args = string()</v> - <v>Node = node()</v> - <v>Reason = timeout | no_rsh | {already_running, Node}</v> - </type> <desc> <p>Starts a slave node in the same way as <c>start/1,2,3</c>, except that the slave node is linked to the currently @@ -151,11 +139,8 @@ slave:start(H, Name, Arg).</code> </desc> </func> <func> - <name>stop(Node) -> ok</name> + <name name="stop" arity="1"/> <fsummary>Stop (kill) a node</fsummary> - <type> - <v>Node = node()</v> - </type> <desc> <p>Stops (kills) a node.</p> </desc> @@ -177,12 +162,8 @@ slave:start(H, Name, Arg).</code> </desc> </func> <func> - <name>pseudo(Master, ServerList) -> ok</name> + <name name="pseudo" arity="2"/> <fsummary>Start a number of pseudo servers</fsummary> - <type> - <v>Master = node()</v> - <v>ServerList = [atom()]</v> - </type> <desc> <p>Starts a number of pseudo servers. A pseudo server is a server with a registered name which does absolutely nothing @@ -198,16 +179,13 @@ rpc:call(N, slave, pseudo, [node(), [pxw_server]]).</code> </desc> </func> <func> - <name>relay(Pid)</name> + <name name="relay" arity="1"/> <fsummary>Run a pseudo server</fsummary> - <type> - <v>Pid = pid()</v> - </type> <desc> <p>Runs a pseudo server. This function never returns any value and the process which executes the function will receive messages. All messages received will simply be passed on to - <c>Pid</c>.</p> + <c><anno>Pid</anno></c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml index 729df1e678..2e7768a1df 100644 --- a/lib/stdlib/doc/src/sofs.xml +++ b/lib/stdlib/doc/src/sofs.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2010</year> + <year>2001</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -181,10 +181,11 @@ the <marker id="canonical_map"></marker><em>canonical map</em> is the function that maps every element of X onto its equivalence class. </p> - <p>Relations as defined above (as sets of ordered pairs) will from - now on be referred to as <em>binary relations</em>. We call a - set of ordered sets (x[1], ..., x[n]) - an <em>(n-ary) relation</em>, and say that the relation is a subset of + <p><marker id="binary_relation"></marker>Relations as defined above + (as sets of ordered pairs) will from now on be referred to as + <em>binary relations</em>. We call a set of ordered sets + (x[1], ..., x[n]) an <marker id="n_ary_relation"></marker> + <em>(n-ary) relation</em>, and say that the relation is a subset of the <marker id="Cartesian_product_tuple"></marker>Cartesian product X[1] × ... × X[n] where x[i] is an element of X[i], 1 <= i <= n. @@ -293,7 +294,8 @@ <c>partition_family/2</c>, <c>projection/2</c>, <c>restriction/3</c>, <c>substitution/2</c>) accept an Erlang function as a means to modify each element of a given unordered - set. Such a function, called SetFun in the following, can be + set. <marker id="set_fun"></marker>Such a function, called + SetFun in the following, can be specified as a functional object (fun), a tuple <c>{external, Fun}</c>, or an integer. If SetFun is specified as a fun, the fun is applied to each element of the @@ -337,34 +339,73 @@ fun(S) -> sofs:partition(1, S) end message when given badly formed arguments or sets the types of which are not compatible.</p> <p>When comparing external sets the operator <c>==/2</c> is used.</p> - <p><em>Types</em></p> - <pre> -anyset() = - an unordered, ordered or atomic set - -binary_relation() = - a binary relation - -bool() = true | false -external_set() = - an external set - -family() = - a family (of subsets) - -function() = - a function - -ordset() = - an ordered set - -relation() = - an n-ary relation - -set() = - an unordered set - -set_of_sets() = - an unordered set of set() - -set_fun() = integer() >= 1 - | {external, fun(external_set()) -> external_set()} - | fun(anyset()) -> anyset() -spec_fun() = {external, fun(external_set()) -> bool()} - | fun(anyset()) -> bool() -type() = - a type - </pre> </description> + <datatypes> + <datatype> + <name name="anyset"></name> + <desc><p>Any kind of set (also included are the atomic sets).</p></desc> + </datatype> + <datatype> + <name name="binary_relation"></name> + <desc><p>A <seealso marker="#binary_relation">binary + relation</seealso>.</p></desc> + </datatype> + <datatype> + <name name="external_set"></name> + <desc><p>An <seealso marker="#external_set">external + set</seealso>.</p></desc> + </datatype> + <datatype> + <name name="family"></name> + <desc><p>A <seealso marker="#family">family</seealso> (of subsets).</p> + </desc> + </datatype> + <datatype> + <name name="a_function"></name> + <desc><p>A <seealso marker="#function">function</seealso>.</p></desc> + </datatype> + <datatype> + <name name="ordset"></name> + <desc><p>An <seealso marker="#sets_definition">ordered + set</seealso>.</p></desc> + </datatype> + <datatype> + <name name="relation"></name> + <desc><p>An <seealso marker="#n_ary_relation">n-ary relation</seealso>. + </p></desc> + </datatype> + <datatype> + <name name="a_set"></name> + <desc><p>An <seealso marker="#sets_definition">unordered + set</seealso>.</p></desc> + </datatype> + <datatype> + <name name="set_of_sets"></name> + <desc><p>An <seealso marker="#sets_definition">unordered + set</seealso> of unordered sets.</p></desc> + </datatype> + <datatype> + <name name="set_fun"></name> + <desc><p>A <seealso marker="#set_fun">SetFun</seealso>.</p></desc> + </datatype> + <datatype> + <name name="spec_fun"></name> + </datatype> + <datatype> + <name name="type"></name> + <desc><p>A <seealso marker="#type">type</seealso>.</p></desc> + </datatype> + <datatype> + <!-- Parameterized opaque types are NYI: --> + <name><marker id="type-tuple_of">tuple_of(T)</marker></name> + <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>a_function(Tuples [, Type]) -> Function</name> + <name name="a_function" arity="1"/> + <name name="a_function" arity="2"/> <fsummary>Create a function.</fsummary> - <type> - <v>Function = function()</v> - <v>Tuples = [tuple()]</v> - <v>Type = type()</v> - </type> <desc> <p>Creates a <seealso marker="#function">function</seealso>. <c>a_function(F, T)</c> is equivalent to @@ -375,16 +416,12 @@ type() = - a type - </pre> </desc> </func> <func> - <name>canonical_relation(SetOfSets) -> BinRel</name> + <name name="canonical_relation" arity="1"/> <fsummary>Return the canonical map.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>SetOfSets = set_of_sets()</v> - </type> <desc> <p>Returns the binary relation containing the elements - (E, Set) such that Set belongs to SetOfSets and E - belongs to Set. If SetOfSets is + (E, Set) such that Set belongs to <anno>SetOfSets</anno> and E + belongs to Set. If SetOfSets is a <seealso marker="#partition">partition</seealso> of a set X and R is the equivalence relation in X induced by SetOfSets, then the returned relation is @@ -398,14 +435,12 @@ type() = - a type - </pre> </desc> </func> <func> - <name>composite(Function1, Function2) -> Function3</name> + <name name="composite" arity="2"/> <fsummary>Return the composite of two functions.</fsummary> - <type> - <v>Function1 = Function2 = Function3 = function()</v> - </type> <desc> <p>Returns the <seealso marker="#composite">composite</seealso> of - the functions Function1 and Function2.</p> + the functions <anno>Function1</anno> and + <anno>Function2</anno>.</p> <pre> 1> <input>F1 = sofs:a_function([{a,1},{b,2},{c,2}]),</input> <input>F2 = sofs:a_function([{1,x},{2,y},{3,z}]),</input> @@ -415,14 +450,9 @@ type() = - a type - </pre> </desc> </func> <func> - <name>constant_function(Set, AnySet) -> Function</name> + <name name="constant_function" arity="2"/> <fsummary>Create the function that maps each element of a set onto another set.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>Function = function()</v> - <v>Set = set()</v> - </type> <desc> <p>Creates the <seealso marker="#function">function</seealso> that maps each element of the set Set onto AnySet.</p> @@ -435,14 +465,11 @@ type() = - a type - </pre> </desc> </func> <func> - <name>converse(BinRel1) -> BinRel2</name> + <name name="converse" arity="1"/> <fsummary>Return the converse of a binary relation.</fsummary> - <type> - <v>BinRel1 = BinRel2 = binary_relation()</v> - </type> <desc> <p>Returns the <seealso marker="#converse">converse</seealso> - of the binary relation BinRel1.</p> + of the binary relation <anno>BinRel1</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{2,b},{3,a}]),</input> <input>R2 = sofs:converse(R1),</input> @@ -451,31 +478,25 @@ type() = - a type - </pre> </desc> </func> <func> - <name>difference(Set1, Set2) -> Set3</name> + <name name="difference" arity="2"/> <fsummary>Return the difference of two sets.</fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#difference">difference</seealso> of - the sets Set1 and Set2.</p> + the sets <anno>Set1</anno> and <anno>Set2</anno>.</p> </desc> </func> <func> - <name>digraph_to_family(Graph [, Type]) -> Family</name> + <name name="digraph_to_family" arity="1"/> + <name name="digraph_to_family" arity="2"/> <fsummary>Create a family from a directed graph.</fsummary> - <type> - <v>Graph = digraph() - see digraph(3) -</v> - <v>Family = family()</v> - <v>Type = type()</v> - </type> <desc> <p>Creates a <seealso marker="#family">family</seealso> from - the directed graph Graph. Each vertex a of Graph is + the directed graph <anno>Graph</anno>. Each vertex a of + <anno>Graph</anno> is represented by a pair (a, {b[1], ..., b[n]}) where the b[i]'s are the out-neighbours of a. If no type is explicitly given, [{atom, [atom]}] is used as type of - the family. It is assumed that Type is + the family. It is assumed that <anno>Type</anno> is a <seealso marker="#valid_type">valid type</seealso> of the external set of the family.</p> <p>If G is a directed graph, it holds that the vertices and @@ -484,15 +505,11 @@ type() = - a type - </pre> </desc> </func> <func> - <name>domain(BinRel) -> Set</name> + <name name="domain" arity="1"/> <fsummary>Return the domain of a binary relation.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#domain">domain</seealso> of - the binary relation BinRel.</p> + the binary relation <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input> <input>S = sofs:domain(R),</input> @@ -501,16 +518,13 @@ type() = - a type - </pre> </desc> </func> <func> - <name>drestriction(BinRel1, Set) -> BinRel2</name> + <name name="drestriction" arity="2"/> <fsummary>Return a restriction of a binary relation.</fsummary> - <type> - <v>BinRel1 = BinRel2 = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> - <p>Returns the difference between the binary relation BinRel1 + <p>Returns the difference between the binary relation + <anno>BinRel1</anno> and the <seealso marker="#restriction">restriction</seealso> - of BinRel1 to Set.</p> + of <anno>BinRel1</anno> to <anno>Set</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input> <input>S = sofs:set([2,4,6]),</input> @@ -522,16 +536,13 @@ type() = - a type - </pre> </desc> </func> <func> - <name>drestriction(SetFun, Set1, Set2) -> Set3</name> + <name name="drestriction" arity="3"/> <fsummary>Return a restriction of a relation.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Set1 = Set2 = Set3 = set()</v> - </type> - <desc> - <p>Returns a subset of Set1 containing those elements that do - not yield an element in Set2 as the result of applying - SetFun.</p> + <desc> + <p>Returns a subset of <anno>Set1</anno> containing those elements + that do + not yield an element in <anno>Set2</anno> as the result of applying + <anno>SetFun</anno>.</p> <pre> 1> <input>SetFun = {external, fun({_A,B,C}) -> {B,C} end},</input> <input>R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),</input> @@ -544,11 +555,8 @@ type() = - a type - </pre> </desc> </func> <func> - <name>empty_set() -> Set</name> + <name name="empty_set" arity="0"/> <fsummary>Return the untyped empty set.</fsummary> - <type> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#sets_definition">untyped empty set</seealso>. <c>empty_set()</c> is equivalent to @@ -556,19 +564,14 @@ type() = - a type - </pre> </desc> </func> <func> - <name>extension(BinRel1, Set, AnySet) -> BinRel2</name> + <name name="extension" arity="3"/> <fsummary>Extend the domain of a binary relation.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>BinRel1 = BinRel2 = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#extension">extension</seealso> of - BinRel1 such that - for each element E in Set that does not belong to the - <seealso marker="#domain">domain</seealso> of BinRel1, - BinRel2 contains the pair (E, AnySet).</p> + <anno>BinRel1</anno> such that + for each element E in <anno>Set</anno> that does not belong to the + <seealso marker="#domain">domain</seealso> of <anno>BinRel1</anno>, + <anno>BinRel2</anno> contains the pair (E, AnySet).</p> <pre> 1> <input>S = sofs:set([b,c]),</input> <input>A = sofs:empty_set(),</input> @@ -579,13 +582,9 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family(Tuples [, Type]) -> Family</name> + <name name="family" arity="1"/> + <name name="family" arity="2"/> <fsummary>Create a family of subsets.</fsummary> - <type> - <v>Family = family()</v> - <v>Tuples = [tuple()]</v> - <v>Type = type()</v> - </type> <desc> <p>Creates a <seealso marker="#family">family of subsets</seealso>. <c>family(F, T)</c> is equivalent to @@ -596,18 +595,17 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_difference(Family1, Family2) -> Family3</name> + <name name="family_difference" arity="2"/> <fsummary>Return the difference of two families.</fsummary> - <type> - <v>Family1 = Family2 = Family3 = family()</v> - </type> <desc> - <p>If Family1 and Family2 + <p>If <anno>Family1</anno> and <anno>Family2</anno> are <seealso marker="#family">families</seealso>, then - Family3 is the family + <anno>Family3</anno> is the family such that the index set is equal to the index set of - Family1, and Family3[i] is the difference between Family1[i] - and Family2[i] if Family2 maps i, Family1[i] otherwise.</p> + <anno>Family1</anno>, and <anno>Family3</anno>[i] is the + difference between <anno>Family1</anno>[i] + and <anno>Family2</anno>[i] if <anno>Family2</anno> maps i, + <anno>Family1</anno>[i] otherwise.</p> <pre> 1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),</input> <input>F2 = sofs:family([{b,[4,5]},{c,[6,7]}]),</input> @@ -617,17 +615,18 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_domain(Family1) -> Family2</name> + <name name="family_domain" arity="1"/> <fsummary>Return a family of domains.</fsummary> - <type> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - and Family1[i] is a binary relation for every i in the index - set of Family1, then Family2 is the family with the same - index set as Family1 such that Family2[i] is - the <seealso marker="#domain">domain</seealso> of Family1[i].</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + and <anno>Family1</anno>[i] is a binary relation for every i + in the index set of <anno>Family1</anno>, + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is + the <seealso marker="#domain">domain</seealso> of + <anno>Family1</anno>[i].</p> <pre> 1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input> <input>F = sofs:family_domain(FR),</input> @@ -636,17 +635,18 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_field(Family1) -> Family2</name> + <name name="family_field" arity="1"/> <fsummary>Return a family of fields.</fsummary> - <type> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - and Family1[i] is a binary relation for every i in the index - set of Family1, then Family2 is the family with the same - index set as Family1 such that Family2[i] is - the <seealso marker="#field">field</seealso> of Family1[i].</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + and <anno>Family1</anno>[i] is a binary relation for every i + in the index set of <anno>Family1</anno>, + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is + the <seealso marker="#field">field</seealso> of + <anno>Family1</anno>[i].</p> <pre> 1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input> <input>F = sofs:family_field(FR),</input> @@ -657,21 +657,21 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_intersection(Family1) -> Family2</name> + <name name="family_intersection" arity="1"/> <fsummary>Return the intersection of a family of sets of sets.</fsummary> - <type> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - and Family1[i] is a set of sets for every i in the index set - of Family1, then Family2 is the family with the same index - set as Family1 such that Family2[i] is - the <seealso marker="#intersection_n">intersection</seealso> of - Family1[i].</p> - <p>If Family1[i] is an empty set for some i, then the process - exits with a <c>badarg</c> message.</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + and <anno>Family1</anno>[i] is a set of sets for every i in + the index set of <anno>Family1</anno>, + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is + the <seealso marker="#intersection_n">intersection</seealso> + of <anno>Family1</anno>[i].</p> + <p>If <anno>Family1</anno>[i] is an empty set for some i, then + the process exits with a <c>badarg</c> message.</p> <pre> 1> <input>F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),</input> <input>F2 = sofs:family_intersection(F1),</input> @@ -680,17 +680,16 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_intersection(Family1, Family2) -> Family3</name> + <name name="family_intersection" arity="2"/> <fsummary>Return the intersection of two families.</fsummary> - <type> - <v>Family1 = Family2 = Family3 = family()</v> - </type> - <desc> - <p>If Family1 and Family2 - are <seealso marker="#family">families</seealso>, then Family3 - is the family such that the index set is the intersection of - Family1's and Family2's index sets, and Family3[i] is the - intersection of Family1[i] and Family2[i].</p> + <desc> + <p>If <anno>Family1</anno> and <anno>Family2</anno> + are <seealso marker="#family">families</seealso>, + then <anno>Family3</anno> is the family such that the index + set is the intersection of <anno>Family1</anno>'s and + <anno>Family2</anno>'s index sets, + and <anno>Family3</anno>[i] is the intersection of + <anno>Family1</anno>[i] and <anno>Family2</anno>[i].</p> <pre> 1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),</input> <input>F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),</input> @@ -700,18 +699,16 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_projection(SetFun, Family1) -> Family2</name> + <name name="family_projection" arity="2"/> <fsummary>Return a family of modified subsets.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Family1 = Family2 = family()</v> - <v>Set = set()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - then Family2 is the family with the same index set as - Family1 such that Family2[i] is the result of calling SetFun - with Family1[i] as argument.</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is the result of + calling <anno>SetFun</anno> with <anno>Family1</anno>[i] as + argument.</p> <pre> 1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input> <input>F2 = sofs:family_projection({sofs, union}, F1),</input> @@ -720,17 +717,18 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_range(Family1) -> Family2</name> + <name name="family_range" arity="1"/> <fsummary>Return a family of ranges.</fsummary> - <type> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - and Family1[i] is a binary relation for every i in the index - set of Family1, then Family2 is the family with the same - index set as Family1 such that Family2[i] is - the <seealso marker="#range">range</seealso> of Family1[i].</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + and <anno>Family1</anno>[i] is a binary relation for every i + in the index set of <anno>Family1</anno>, + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is + the <seealso marker="#range">range</seealso> of + <anno>Family1</anno>[i].</p> <pre> 1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input> <input>F = sofs:family_range(FR),</input> @@ -739,22 +737,21 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_specification(Fun, Family1) -> Family2</name> + <name name="family_specification" arity="2"/> <fsummary>Select a subset of a family using a predicate.</fsummary> - <type> - <v>Fun = spec_fun()</v> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso>, - then Family2 is - the <seealso marker="#restriction">restriction</seealso> of - Family1 to those elements i of the - index set for which Fun applied to Family1[i] returns - <c>true</c>. If Fun is a tuple <c>{external, Fun2}</c>, - Fun2 is applied to - the <seealso marker="#external_set">external set</seealso> of - Family1[i], otherwise Fun is applied to Family1[i].</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso>, + then <anno>Family2</anno> is + the <seealso marker="#restriction">restriction</seealso> of + <anno>Family1</anno> to those elements i of the index set + for which <anno>Fun</anno> applied + to <anno>Family1</anno>[i] returns + <c>true</c>. If <anno>Fun</anno> is a + tuple <c>{external, Fun2}</c>, Fun2 is applied to + the <seealso marker="#external_set">external set</seealso> + of <anno>Family1</anno>[i], otherwise <anno>Fun</anno> is + applied to <anno>Family1</anno>[i].</p> <pre> 1> <input>F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),</input> <input>SpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,</input> @@ -764,24 +761,22 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_to_digraph(Family [, GraphType]) -> Graph</name> + <name name="family_to_digraph" arity="1"/> + <name name="family_to_digraph" arity="2"/> <fsummary>Create a directed graph from a family.</fsummary> - <type> - <v>Graph = digraph()</v> - <v>Family = family()</v> - <v>GraphType = - see digraph(3) -</v> - </type> <desc> <p>Creates a directed graph from - the <seealso marker="#family">family</seealso> Family. For each - pair (a, {b[1], ..., b[n]}) of Family, the vertex + the <seealso marker="#family">family</seealso> <anno>Family</anno>. + For each pair (a, {b[1], ..., b[n]}) + of <anno>Family</anno>, the vertex a as well the edges (a, b[i]) for 1 <= i <= n are added to a newly created directed graph.</p> - <p>If no graph type is given, <c>digraph:new/1</c> is used for - creating the directed graph, otherwise the GraphType + <p>If no graph type is given <seealso marker="digraph#new/0"> + digraph:new/0</seealso> is used for + creating the directed graph, otherwise the <anno>GraphType</anno> argument is passed on as second argument to - <c>digraph:new/2</c>.</p> + <seealso marker="digraph#new/1">digraph:new/1</seealso>.</p> <p>It F is a family, it holds that F is a subset of <c>digraph_to_family(family_to_digraph(F), type(F))</c>. Equality holds if <c>union_of_family(F)</c> is a subset of @@ -791,17 +786,15 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_to_relation(Family) -> BinRel</name> + <name name="family_to_relation" arity="1"/> <fsummary>Create a binary relation from a family.</fsummary> - <type> - <v>Family = family()</v> - <v>BinRel = binary_relation()</v> - </type> - <desc> - <p>If Family is a <seealso marker="#family">family</seealso>, - then BinRel is the binary relation containing all pairs - (i, x) such that i belongs to the index set of Family - and x belongs to Family[i].</p> + <desc> + <p>If <anno>Family</anno> is + a <seealso marker="#family">family</seealso>, + then <anno>BinRel</anno> is the binary relation containing + all pairs (i, x) such that i belongs to the index set + of <anno>Family</anno> and x belongs + to <anno>Family</anno>[i].</p> <pre> 1> <input>F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),</input> <input>R = sofs:family_to_relation(F),</input> @@ -810,17 +803,18 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_union(Family1) -> Family2</name> + <name name="family_union" arity="1"/> <fsummary>Return the union of a family of sets of sets.</fsummary> - <type> - <v>Family1 = Family2 = family()</v> - </type> - <desc> - <p>If Family1 is a <seealso marker="#family">family</seealso> - and Family1[i] is a set of sets for each i in the index set - of Family1, then Family2 is the family with the same index - set as Family1 such that Family2[i] is - the <seealso marker="#union_n">union</seealso> of Family1[i].</p> + <desc> + <p>If <anno>Family1</anno> is + a <seealso marker="#family">family</seealso> + and <anno>Family1</anno>[i] is a set of sets for each i in + the index set of <anno>Family1</anno>, + then <anno>Family2</anno> is the family with the same index + set as <anno>Family1</anno> such + that <anno>Family2</anno>[i] is + the <seealso marker="#union_n">union</seealso> of + <anno>Family1</anno>[i].</p> <pre> 1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input> <input>F2 = sofs:family_union(F1),</input> @@ -831,18 +825,18 @@ type() = - a type - </pre> </desc> </func> <func> - <name>family_union(Family1, Family2) -> Family3</name> + <name name="family_union" arity="2"/> <fsummary>Return the union of two families.</fsummary> - <type> - <v>Family1 = Family2 = Family3 = family()</v> - </type> - <desc> - <p>If Family1 and Family2 - are <seealso marker="#family">families</seealso>, then Family3 - is the family such that the index set is the union of Family1's - and Family2's index sets, and Family3[i] is the union of - Family1[i] and Family2[i] if both maps i, Family1[i] or - Family2[i] otherwise.</p> + <desc> + <p>If <anno>Family1</anno> and <anno>Family2</anno> + are <seealso marker="#family">families</seealso>, + then <anno>Family3</anno> is the family such that the index + set is the union of <anno>Family1</anno>'s + and <anno>Family2</anno>'s index sets, + and <anno>Family3</anno>[i] is the union + of <anno>Family1</anno>[i] and <anno>Family2</anno>[i] if + both maps i, <anno>Family1</anno>[i] + or <anno>Family2</anno>[i] otherwise.</p> <pre> 1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),</input> <input>F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),</input> @@ -852,15 +846,11 @@ type() = - a type - </pre> </desc> </func> <func> - <name>field(BinRel) -> Set</name> + <name name="field" arity="1"/> <fsummary>Return the field of a binary relation.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#field">field</seealso> of the - binary relation BinRel.</p> + binary relation <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input> <input>S = sofs:field(R),</input> @@ -871,31 +861,24 @@ type() = - a type - </pre> </desc> </func> <func> - <name>from_external(ExternalSet, Type) -> AnySet</name> + <name name="from_external" arity="2"/> <fsummary>Create a set.</fsummary> - <type> - <v>ExternalSet = external_set()</v> - <v>AnySet = anyset()</v> - <v>Type = type()</v> - </type> <desc> <p>Creates a set from the <seealso marker="#external_set">external - set</seealso> ExternalSet - and the <seealso marker="#type">type</seealso> Type. It is - assumed that Type is a <seealso marker="#valid_type">valid - type</seealso> of ExternalSet.</p> + set</seealso> <anno>ExternalSet</anno> + and the <seealso marker="#type">type</seealso> <anno>Type</anno>. + It is assumed that <anno>Type</anno> is + a <seealso marker="#valid_type">valid + type</seealso> of <anno>ExternalSet</anno>.</p> </desc> </func> <func> - <name>from_sets(ListOfSets) -> Set</name> + <name name="from_sets" arity="1" clause_i="1"/> <fsummary>Create a set out of a list of sets.</fsummary> - <type> - <v>Set = set()</v> - <v>ListOfSets = [anyset()]</v> - </type> <desc> <p>Returns the <seealso marker="#sets_definition">unordered - set</seealso> containing the sets of the list ListOfSets.</p> + set</seealso> containing the sets of the list + <anno>ListOfSets</anno>.</p> <pre> 1> <input>S1 = sofs:relation([{a,1},{b,2}]),</input> <input>S2 = sofs:relation([{x,3},{y,4}]),</input> @@ -905,38 +888,33 @@ type() = - a type - </pre> </desc> </func> <func> - <name>from_sets(TupleOfSets) -> Ordset</name> + <name name="from_sets" arity="1" clause_i="2"/> <fsummary>Create an ordered set out of a tuple of sets.</fsummary> - <type> - <v>Ordset = ordset()</v> - <v>TupleOfSets = tuple-of(anyset())</v> - </type> <desc> <p>Returns the <seealso marker="#sets_definition">ordered set</seealso> containing the sets of the non-empty tuple - TupleOfSets.</p> + <anno>TupleOfSets</anno>.</p> </desc> </func> <func> - <name>from_term(Term [, Type]) -> AnySet</name> + <name name="from_term" arity="1"/> + <name name="from_term" arity="2"/> <fsummary>Create a set.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>Term = term()</v> - <v>Type = type()</v> - </type> <desc> <p><marker id="from_term"></marker>Creates an element of <seealso marker="#sets_definition">Sets</seealso> by - traversing the term Term, sorting lists, removing duplicates and + traversing the term <anno>Term</anno>, sorting lists, + removing duplicates and deriving or verifying a <seealso marker="#valid_type">valid type</seealso> for the so obtained external set. An - explicitly given <seealso marker="#type">type</seealso> Type + explicitly given <seealso marker="#type">type</seealso> + <anno>Type</anno> can be used to limit the depth of the traversal; an atomic type stops the traversal, as demonstrated by this example where "foo" and {"foo"} are left unmodified:</p> <pre> -1> <input>S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}], [{atom,[atom]}]),</input> +1> <input>S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}], +[{atom,[atom]}]),</input> <input>sofs:to_external(S).</input> [{{"foo"},[1]},{"foo",[2]}]</pre> <p><c>from_term</c> can be used for creating atomic or ordered @@ -963,15 +941,12 @@ type() = - a type - </pre> </desc> </func> <func> - <name>image(BinRel, Set1) -> Set2</name> + <name name="image" arity="2"/> <fsummary>Return the image of a set under a binary relation.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#image">image</seealso> of the - set Set1 under the binary relation BinRel.</p> + set <anno>Set1</anno> under the binary + relation <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),</input> <input>S1 = sofs:set([1,2]),</input> @@ -981,42 +956,32 @@ type() = - a type - </pre> </desc> </func> <func> - <name>intersection(SetOfSets) -> Set</name> + <name name="intersection" arity="1"/> <fsummary>Return the intersection of a set of sets.</fsummary> - <type> - <v>Set = set()</v> - <v>SetOfSets = set_of_sets()</v> - </type> <desc> <p>Returns the <seealso marker="#intersection_n">intersection</seealso> of - the set of sets SetOfSets.</p> + the set of sets <anno>SetOfSets</anno>.</p> <p>Intersecting an empty set of sets exits the process with a <c>badarg</c> message.</p> </desc> </func> <func> - <name>intersection(Set1, Set2) -> Set3</name> + <name name="intersection" arity="2"/> <fsummary>Return the intersection of two sets.</fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#intersection">intersection</seealso> of - Set1 and Set2.</p> + <anno>Set1</anno> and <anno>Set2</anno>.</p> </desc> </func> <func> - <name>intersection_of_family(Family) -> Set</name> + <name name="intersection_of_family" arity="1"/> <fsummary>Return the intersection of a family.</fsummary> - <type> - <v>Family = family()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the intersection of - the <seealso marker="#family">family</seealso> Family.</p> + the <seealso marker="#family">family</seealso> <anno>Family</anno>. + </p> <p>Intersecting an empty family exits the process with a <c>badarg</c> message.</p> <pre> @@ -1027,14 +992,11 @@ type() = - a type - </pre> </desc> </func> <func> - <name>inverse(Function1) -> Function2</name> + <name name="inverse" arity="1"/> <fsummary>Return the inverse of a function.</fsummary> - <type> - <v>Function1 = Function2 = function()</v> - </type> <desc> <p>Returns the <seealso marker="#inverse">inverse</seealso> - of the function Function1.</p> + of the function <anno>Function1</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input> <input>R2 = sofs:inverse(R1),</input> @@ -1043,16 +1005,13 @@ type() = - a type - </pre> </desc> </func> <func> - <name>inverse_image(BinRel, Set1) -> Set2</name> + <name name="inverse_image" arity="2"/> <fsummary>Return the inverse image of a set under a binary relation.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns the <seealso marker="#inverse_image">inverse - image</seealso> of Set1 under the binary relation BinRel.</p> + <p>Returns the <seealso marker="#inverse_image">inverse + image</seealso> of <anno>Set1</anno> under the binary + relation <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),</input> <input>S1 = sofs:set([c,d,e]),</input> @@ -1062,52 +1021,38 @@ type() = - a type - </pre> </desc> </func> <func> - <name>is_a_function(BinRel) -> Bool</name> + <name name="is_a_function" arity="1"/> <fsummary>Test for a function.</fsummary> - <type> - <v>Bool = bool()</v> - <v>BinRel = binary_relation()</v> - </type> <desc> - <p>Returns <c>true</c> if the binary relation BinRel is a - <seealso marker="#function">function</seealso> or the + <p>Returns <c>true</c> if the binary relation <anno>BinRel</anno> + is a <seealso marker="#function">function</seealso> or the untyped empty set, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_disjoint(Set1, Set2) -> Bool</name> + <name name="is_disjoint" arity="2"/> <fsummary>Test for disjoint sets.</fsummary> - <type> - <v>Bool = bool()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns <c>true</c> if Set1 and Set2 + <p>Returns <c>true</c> if <anno>Set1</anno> + and <anno>Set2</anno> are <seealso marker="#disjoint">disjoint</seealso>, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_empty_set(AnySet) -> Bool</name> + <name name="is_empty_set" arity="1"/> <fsummary>Test for an empty set.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>Bool = bool()</v> - </type> <desc> - <p>Returns <c>true</c> if Set is an empty unordered set, - <c>false</c> otherwise.</p> + <p>Returns <c>true</c> if <anno>AnySet</anno> is an empty + unordered set, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_equal(AnySet1, AnySet2) -> Bool</name> + <name name="is_equal" arity="2"/> <fsummary>Test two sets for equality.</fsummary> - <type> - <v>AnySet1 = AnySet2 = anyset()</v> - <v>Bool = bool()</v> - </type> <desc> - <p>Returns <c>true</c> if the AnySet1 and AnySet2 + <p>Returns <c>true</c> if the <anno>AnySet1</anno> + and <anno>AnySet2</anno> are <seealso marker="#equal">equal</seealso>, <c>false</c> otherwise. This example shows that <c>==/2</c> is used when comparing sets for equality:</p> @@ -1119,67 +1064,49 @@ true</pre> </desc> </func> <func> - <name>is_set(AnySet) -> Bool</name> + <name name="is_set" arity="1"/> <fsummary>Test for an unordered set.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>Bool = bool()</v> - </type> <desc> - <p>Returns <c>true</c> if AnySet is + <p>Returns <c>true</c> if <anno>AnySet</anno> is an <seealso marker="#sets_definition">unordered set</seealso>, and - <c>false</c> if AnySet is an ordered set or an atomic set.</p> + <c>false</c> if <anno>AnySet</anno> is an ordered set or an + atomic set.</p> </desc> </func> <func> - <name>is_sofs_set(Term) -> Bool</name> + <name name="is_sofs_set" arity="1"/> <fsummary>Test for an unordered set.</fsummary> - <type> - <v>Bool = bool()</v> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if Term is + <p>Returns <c>true</c> if <anno>Term</anno> is an <seealso marker="#sets_definition">unordered set</seealso>, an ordered set or an atomic set, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_subset(Set1, Set2) -> Bool</name> + <name name="is_subset" arity="2"/> <fsummary>Test two sets for subset.</fsummary> - <type> - <v>Bool = bool()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns <c>true</c> if Set1 is - a <seealso marker="#subset">subset</seealso> of Set2, <c>false</c> - otherwise.</p> + <p>Returns <c>true</c> if <anno>Set1</anno> is + a <seealso marker="#subset">subset</seealso> + of <anno>Set2</anno>, <c>false</c> otherwise.</p> </desc> </func> <func> - <name>is_type(Term) -> Bool</name> + <name name="is_type" arity="1"/> <fsummary>Test for a type.</fsummary> - <type> - <v>Bool = bool()</v> - <v>Term = term()</v> - </type> <desc> - <p>Returns <c>true</c> if the term Term is + <p>Returns <c>true</c> if the term <anno>Term</anno> is a <seealso marker="#type">type</seealso>.</p> </desc> </func> <func> - <name>join(Relation1, I, Relation2, J) -> Relation3</name> + <name name="join" arity="4"/> <fsummary>Return the join of two relations.</fsummary> - <type> - <v>Relation1 = Relation2 = Relation3 = relation()</v> - <v>I = J = integer() > 0</v> - </type> <desc> <p>Returns the <seealso marker="#natural_join">natural - join</seealso> of the relations Relation1 and Relation2 on - coordinates I and J.</p> + join</seealso> of the relations <anno>Relation1</anno> + and <anno>Relation2</anno> on coordinates <anno>I</anno> and + <anno>J</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{a,x,1},{b,y,2}]),</input> <input>R2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),</input> @@ -1189,20 +1116,17 @@ true</pre> </desc> </func> <func> - <name>multiple_relative_product(TupleOfBinRels, BinRel1) -> BinRel2</name> + <name name="multiple_relative_product" arity="2"/> <fsummary>Return the multiple relative product of a tuple of binary relations and a relation.</fsummary> - <type> - <v>TupleOfBinRels = tuple-of(BinRel)</v> - <v>BinRel = BinRel1 = BinRel2 = binary_relation()</v> - </type> - <desc> - <p>If TupleOfBinRels is a non-empty tuple - {R[1], ..., R[n]} of binary relations and BinRel1 - is a binary relation, then BinRel2 is + <desc> + <p>If <anno>TupleOfBinRels</anno> is a non-empty tuple + {R[1], ..., R[n]} of binary relations + and <anno>BinRel1</anno> is a binary relation, + then <anno>BinRel2</anno> is the <seealso marker="#multiple_relative_product">multiple relative product</seealso> of the ordered set - (R[i], ..., R[n]) and BinRel1.</p> + (R[i], ..., R[n]) and <anno>BinRel1</anno>.</p> <pre> 1> <input>Ri = sofs:relation([{a,1},{b,2},{c,3}]),</input> <input>R = sofs:relation([{a,b},{b,c},{c,a}]),</input> @@ -1212,29 +1136,21 @@ true</pre> </desc> </func> <func> - <name>no_elements(ASet) -> NoElements</name> + <name name="no_elements" arity="1"/> <fsummary>Return the number of elements of a set.</fsummary> - <type> - <v>ASet = set() | ordset()</v> - <v>NoElements = integer() >= 0 </v> - </type> <desc> <p>Returns the number of elements of the ordered or unordered - set ASet.</p> + set <anno>ASet</anno>.</p> </desc> </func> <func> - <name>partition(SetOfSets) -> Partition</name> + <name name="partition" arity="1"/> <fsummary>Return the coarsest partition given a set of sets.</fsummary> - <type> - <v>SetOfSets = set_of_sets()</v> - <v>Partition = set()</v> - </type> <desc> <p>Returns the <seealso marker="#partition">partition</seealso> of - the union of the set of sets SetOfSets such that two + the union of the set of sets <anno>SetOfSets</anno> such that two elements are considered equal if they belong to the same - elements of SetOfSets.</p> + elements of <anno>SetOfSets</anno>.</p> <pre> 1> <input>Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),</input> <input>Sets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),</input> @@ -1244,17 +1160,12 @@ true</pre> </desc> </func> <func> - <name>partition(SetFun, Set) -> Partition</name> + <name name="partition" arity="2"/> <fsummary>Return a partition of a set.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Partition = set()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#partition">partition</seealso> of - Set such that two elements are considered equal if the - results of applying SetFun are equal.</p> + <anno>Set</anno> such that two elements are considered equal + if the results of applying <anno>SetFun</anno> are equal.</p> <pre> 1> <input>Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),</input> <input>SetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,</input> @@ -1264,19 +1175,16 @@ true</pre> </desc> </func> <func> - <name>partition(SetFun, Set1, Set2) -> {Set3, Set4}</name> + <name name="partition" arity="3"/> <fsummary>Return a partition of a set.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Set1 = Set2 = Set3 = Set4 = set()</v> - </type> <desc> <p>Returns a pair of sets that, regarded as constituting a set, forms a <seealso marker="#partition">partition</seealso> of - Set1. If the - result of applying SetFun to an element of Set1 yields an - element in Set2, the element belongs to Set3, otherwise the - element belongs to Set4.</p> + <anno>Set1</anno>. If the + result of applying <anno>SetFun</anno> to an element + of <anno>Set1</anno> yields an element in <anno>Set2</anno>, + the element belongs to <anno>Set3</anno>, otherwise the + element belongs to <anno>Set4</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input> <input>S = sofs:set([2,4,6]),</input> @@ -1289,21 +1197,17 @@ true</pre> </desc> </func> <func> - <name>partition_family(SetFun, Set) -> Family</name> + <name name="partition_family" arity="2"/> <fsummary>Return a family indexing a partition.</fsummary> - <type> - <v>Family = family()</v> - <v>SetFun = set_fun()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#family">family</seealso> - Family where the indexed set is - a <seealso marker="#partition">partition</seealso> of Set - such that two elements are considered equal if the results - of applying SetFun are the same value i. This i is the index - that Family maps onto - the <seealso marker="#equivalence_class">equivalence + <anno>Family</anno> where the indexed set is + a <seealso marker="#partition">partition</seealso> + of <anno>Set</anno> such that two elements are considered + equal if the results of applying <anno>SetFun</anno> are the + same value i. This i is the index that <anno>Family</anno> + maps onto + the <seealso marker="#equivalence_class">equivalence class</seealso>.</p> <pre> 1> <input>S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),</input> @@ -1314,18 +1218,15 @@ true</pre> </desc> </func> <func> - <name>product(TupleOfSets) -> Relation</name> + <name name="product" arity="1"/> <fsummary>Return the Cartesian product of a tuple of sets.</fsummary> - <type> - <v>Relation = relation()</v> - <v>TupleOfSets = tuple-of(set())</v> - </type> <desc> <p>Returns the <seealso marker="#Cartesian_product_tuple">Cartesian product</seealso> of the non-empty tuple of sets - TupleOfSets. If (x[1], ..., x[n]) is an element of - the n-ary relation Relation, then x[i] is drawn from element - i of TupleOfSets.</p> + <anno>TupleOfSets</anno>. If (x[1], ..., x[n]) is + an element of the n-ary relation <anno>Relation</anno>, then + x[i] is drawn from element i + of <anno>TupleOfSets</anno>.</p> <pre> 1> <input>S1 = sofs:set([a,b]),</input> <input>S2 = sofs:set([1,2]),</input> @@ -1336,15 +1237,12 @@ true</pre> </desc> </func> <func> - <name>product(Set1, Set2) -> BinRel</name> + <name name="product" arity="2"/> <fsummary>Return the Cartesian product of two sets.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#Cartesian_product">Cartesian - product</seealso> of Set1 and Set2.</p> + product</seealso> of <anno>Set1</anno> + and <anno>Set2</anno>.</p> <pre> 1> <input>S1 = sofs:set([1,2]),</input> <input>S2 = sofs:set([a,b]),</input> @@ -1356,19 +1254,16 @@ true</pre> </desc> </func> <func> - <name>projection(SetFun, Set1) -> Set2</name> + <name name="projection" arity="2"/> <fsummary>Return a set of substituted elements.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> <p>Returns the set created by substituting each element of - Set1 by the result of applying SetFun to the element.</p> - <p>If SetFun is a number i >= 1 and Set1 is a - relation, then the returned set is - the <seealso marker="#projection">projection</seealso> of Set1 - onto coordinate i.</p> + <anno>Set1</anno> by the result of + applying <anno>SetFun</anno> to the element.</p> + <p>If <anno>SetFun</anno> is a number i >= 1 and + <anno>Set1</anno> is a relation, then the returned set is + the <seealso marker="#projection">projection</seealso> of + <anno>Set1</anno> onto coordinate i.</p> <pre> 1> <input>S1 = sofs:from_term([{1,a},{2,b},{3,a}]),</input> <input>S2 = sofs:projection(2, S1),</input> @@ -1377,15 +1272,11 @@ true</pre> </desc> </func> <func> - <name>range(BinRel) -> Set</name> + <name name="range" arity="1"/> <fsummary>Return the range of a binary relation.</fsummary> - <type> - <v>BinRel = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#range">range</seealso> of the - binary relation BinRel.</p> + binary relation <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input> <input>S = sofs:range(R),</input> @@ -1394,41 +1285,33 @@ true</pre> </desc> </func> <func> - <name>relation(Tuples [, Type]) -> Relation</name> + <name name="relation" arity="1"/> + <name name="relation" arity="2"/> <fsummary>Create a relation.</fsummary> - <type> - <v>N = integer()</v> - <v>Type = N | type()</v> - <v>Relation = relation()</v> - <v>Tuples = [tuple()]</v> - </type> <desc> <p>Creates a <seealso marker="#relation">relation</seealso>. <c>relation(R, T)</c> is equivalent to <c>from_term(R, T)</c>, if T is a <seealso marker="#type">type</seealso> and the result is a - relation. If Type is an integer N, then + relation. If <anno>Type</anno> is an integer N, then <c>[{atom, ..., atom}])</c>, where the size of the tuple is N, is used as type of the relation. If no type is - explicitly given, the size of the first tuple of Tuples is + explicitly given, the size of the first tuple of + <anno>Tuples</anno> is used if there is such a tuple. <c>relation([])</c> is equivalent to <c>relation([], 2)</c>.</p> </desc> </func> <func> - <name>relation_to_family(BinRel) -> Family</name> + <name name="relation_to_family" arity="1"/> <fsummary>Create a family from a binary relation.</fsummary> - <type> - <v>Family = family()</v> - <v>BinRel = binary_relation()</v> - </type> <desc> <p>Returns the <seealso marker="#family">family</seealso> - Family such that the index set is equal to + <anno>Family</anno> such that the index set is equal to the <seealso marker="#domain">domain</seealso> of the binary - relation BinRel, and Family[i] is + relation <anno>BinRel</anno>, and <anno>Family</anno>[i] is the <seealso marker="#image">image</seealso> of the set of i - under BinRel.</p> + under <anno>BinRel</anno>.</p> <pre> 1> <input>R = sofs:relation([{b,1},{c,2},{c,3}]),</input> <input>F = sofs:relation_to_family(R),</input> @@ -1437,63 +1320,57 @@ true</pre> </desc> </func> <func> - <name>relative_product(TupleOfBinRels [, BinRel1]) -> BinRel2</name> - <fsummary>Return the relative product of a tuple of binary relations + <name name="relative_product" arity="1"/> + <name name="relative_product" arity="2" clause_i="1"/> + <fsummary>Return the relative product of a list of binary relations and a binary relation.</fsummary> - <type> - <v>TupleOfBinRels = tuple-of(BinRel)</v> - <v>BinRel = BinRel1 = BinRel2 = binary_relation()</v> - </type> - <desc> - <p>If TupleOfBinRels is a non-empty tuple - {R[1], ..., R[n]} of binary relations and BinRel1 - is a binary relation, then BinRel2 is - the <seealso marker="#tuple_relative_product">relative - product</seealso> of the ordered set (R[i], ..., R[n]) - and BinRel1.</p> - <p>If BinRel1 is omitted, the relation of equality between the - elements of - the <seealso marker="#Cartesian_product_tuple">Cartesian - product</seealso> of the ranges of R[i], + <desc> + <p>If <anno>ListOfBinRels</anno> is a non-empty list + [R[1], ..., R[n]] of binary relations and + <anno>BinRel1</anno> + is a binary relation, then <anno>BinRel2</anno> is the <seealso + marker="#tuple_relative_product">relative product</seealso> + of the ordered set (R[i], ..., R[n]) and + <anno>BinRel1</anno>.</p> + <p>If <anno>BinRel1</anno> is omitted, the relation of equality + between the elements of + the <seealso marker="#Cartesian_product_tuple">Cartesian + product</seealso> of the ranges of R[i], range R[1] × ... × range R[n], is used instead (intuitively, nothing is "lost").</p> <pre> 1> <input>TR = sofs:relation([{1,a},{1,aa},{2,b}]),</input> <input>R1 = sofs:relation([{1,u},{2,v},{3,c}]),</input> -<input>R2 = sofs:relative_product({TR, R1}),</input> +<input>R2 = sofs:relative_product([TR, R1]),</input> <input>sofs:to_external(R2).</input> [{1,{a,u}},{1,{aa,u}},{2,{b,v}}]</pre> - <p>Note that <c>relative_product({R1}, R2)</c> is + <p>Note that <c>relative_product([R1], R2)</c> is different from <c>relative_product(R1, R2)</c>; the - tuple of one element is not identified with the element + list of one element is not identified with the element itself.</p> </desc> </func> <func> - <name>relative_product(BinRel1, BinRel2) -> BinRel3</name> + <name name="relative_product" arity="2" clause_i="2"/> <fsummary>Return the relative product of two binary relations.</fsummary> - <type> - <v>BinRel1 = BinRel2 = BinRel3 = binary_relation()</v> - </type> <desc> <p><marker id="relprod_impl"></marker>Returns the <seealso marker="#relative_product">relative - product</seealso> of the binary relations BinRel1 and BinRel2.</p> + product</seealso> of the binary relations <anno>BinRel1</anno> + and <anno>BinRel2</anno>.</p> </desc> </func> <func> - <name>relative_product1(BinRel1, BinRel2) -> BinRel3</name> + <name name="relative_product1" arity="2"/> <fsummary>Return the relative_product of two binary relations.</fsummary> - <type> - <v>BinRel1 = BinRel2 = BinRel3 = binary_relation()</v> - </type> <desc> <p>Returns the <seealso marker="#relative_product">relative product</seealso> of the <seealso marker="#converse">converse</seealso> of the - binary relation BinRel1 and the binary relation BinRel2.</p> + binary relation <anno>BinRel1</anno> and the binary + relation <anno>BinRel2</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{1,aa},{2,b}]),</input> <input>R2 = sofs:relation([{1,u},{2,v},{3,c}]),</input> @@ -1505,15 +1382,12 @@ true</pre> </desc> </func> <func> - <name>restriction(BinRel1, Set) -> BinRel2</name> + <name name="restriction" arity="2"/> <fsummary>Return a restriction of a binary relation.</fsummary> - <type> - <v>BinRel1 = BinRel2 = binary_relation()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the <seealso marker="#restriction">restriction</seealso> of - the binary relation BinRel1 to Set.</p> + the binary relation <anno>BinRel1</anno> + to <anno>Set</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input> <input>S = sofs:set([1,2,4]),</input> @@ -1523,15 +1397,12 @@ true</pre> </desc> </func> <func> - <name>restriction(SetFun, Set1, Set2) -> Set3</name> + <name name="restriction" arity="3"/> <fsummary>Return a restriction of a set.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> - <p>Returns a subset of Set1 containing those elements that - yield an element in Set2 as the result of applying SetFun.</p> + <p>Returns a subset of <anno>Set1</anno> containing those + elements that yield an element in <anno>Set2</anno> as the + result of applying <anno>SetFun</anno>.</p> <pre> 1> <input>S1 = sofs:relation([{1,a},{2,b},{3,c}]),</input> <input>S2 = sofs:set([b,c,d]),</input> @@ -1541,13 +1412,9 @@ true</pre> </desc> </func> <func> - <name>set(Terms [, Type]) -> Set</name> + <name name="set" arity="1"/> + <name name="set" arity="2"/> <fsummary>Create a set of atoms or any type of sets.</fsummary> - <type> - <v>Set = set()</v> - <v>Terms = [term()]</v> - <v>Type = type()</v> - </type> <desc> <p>Creates an <seealso marker="#sets_definition">unordered set</seealso>. <c>set(L, T)</c> is equivalent to @@ -1557,18 +1424,16 @@ true</pre> </desc> </func> <func> - <name>specification(Fun, Set1) -> Set2</name> + <name name="specification" arity="2"/> <fsummary>Select a subset using a predicate.</fsummary> - <type> - <v>Fun = spec_fun()</v> - <v>Set1 = Set2 = set()</v> - </type> <desc> - <p>Returns the set containing every element of Set1 for which - Fun returns <c>true</c>. If Fun is a tuple + <p>Returns the set containing every element + of <anno>Set1</anno> for which <anno>Fun</anno> + returns <c>true</c>. If <anno>Fun</anno> is a tuple <c>{external, Fun2}</c>, Fun2 is applied to the <seealso marker="#external_set">external set</seealso> of - each element, otherwise Fun is applied to each element.</p> + each element, otherwise <anno>Fun</anno> is applied to each + element.</p> <pre> 1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input> <input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input> @@ -1579,15 +1444,13 @@ true</pre> </desc> </func> <func> - <name>strict_relation(BinRel1) -> BinRel2</name> + <name name="strict_relation" arity="1"/> <fsummary>Return the strict relation corresponding to a given relation.</fsummary> - <type> - <v>BinRel1 = BinRel2 = binary_relation()</v> - </type> <desc> <p>Returns the <seealso marker="#strict_relation">strict - relation</seealso> corresponding to the binary relation BinRel1.</p> + relation</seealso> corresponding to the binary + relation <anno>BinRel1</anno>.</p> <pre> 1> <input>R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),</input> <input>R2 = sofs:strict_relation(R1),</input> @@ -1596,16 +1459,13 @@ true</pre> </desc> </func> <func> - <name>substitution(SetFun, Set1) -> Set2</name> + <name name="substitution" arity="2"/> <fsummary>Return a function with a given set as domain.</fsummary> - <type> - <v>SetFun = set_fun()</v> - <v>Set1 = Set2 = set()</v> - </type> - <desc> - <p>Returns a function, the domain of which is Set1. The value - of an element of the domain is the result of applying SetFun - to the element.</p> + <desc> + <p>Returns a function, the domain of which + is <anno>Set1</anno>. The value of an element of the domain + is the result of applying <anno>SetFun</anno> to the + element.</p> <pre> 1> <input>L = [{a,1},{b,2}].</input> [{a,1},{b,2}] @@ -1647,14 +1507,12 @@ images2(SetOfSets, BinRel) -> </desc> </func> <func> - <name>symdiff(Set1, Set2) -> Set3</name> + <name name="symdiff" arity="2"/> <fsummary>Return the symmetric difference of two sets.</fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#symmetric_difference">symmetric - difference</seealso> (or the Boolean sum) of Set1 and Set2.</p> + difference</seealso> (or the Boolean sum) + of <anno>Set1</anno> and <anno>Set2</anno>.</p> <pre> 1> <input>S1 = sofs:set([1,2,3]),</input> <input>S2 = sofs:set([2,3,4]),</input> @@ -1664,88 +1522,67 @@ images2(SetOfSets, BinRel) -> </desc> </func> <func> - <name>symmetric_partition(Set1, Set2) -> {Set3, Set4, Set5}</name> + <name name="symmetric_partition" arity="2"/> <fsummary>Return a partition of two sets.</fsummary> - <type> - <v>Set1 = Set2 = Set3 = Set4 = Set5 = set()</v> - </type> <desc> - <p>Returns a triple of sets: Set3 contains the elements - of Set1 that do not belong to Set2; Set4 contains the - elements of Set1 that belong to Set2; Set5 contains the - elements of Set2 that do not belong to Set1.</p> + <p>Returns a triple of sets: <anno>Set3</anno> contains the + elements of <anno>Set1</anno> that do not belong + to <anno>Set2</anno>; <anno>Set4</anno> contains the + elements of <anno>Set1</anno> that belong + to <anno>Set2</anno>; <anno>Set5</anno> contains the + elements of <anno>Set2</anno> that do not belong + to <anno>Set1</anno>.</p> </desc> </func> <func> - <name>to_external(AnySet) -> ExternalSet</name> + <name name="to_external" arity="1"/> <fsummary>Return the elements of a set.</fsummary> - <type> - <v>ExternalSet = external_set()</v> - <v>AnySet = anyset()</v> - </type> <desc> <p>Returns the <seealso marker="#external_set">external set</seealso> of an atomic, ordered or unordered set.</p> </desc> </func> <func> - <name>to_sets(ASet) -> Sets</name> + <name name="to_sets" arity="1"/> <fsummary>Return a list or a tuple of the elements of set.</fsummary> - <type> - <v>ASet = set() | ordset()</v> - <v>Sets = tuple_of(AnySet) | [AnySet]</v> - </type> <desc> - <p>Returns the elements of the ordered set ASet as a tuple of - sets, and the elements of the unordered set ASet as a sorted - list of sets without duplicates.</p> + <p>Returns the elements of the ordered set <anno>ASet</anno> + as a tuple of sets, and the elements of the unordered set + <anno>ASet</anno> as a sorted list of sets without + duplicates.</p> </desc> </func> <func> - <name>type(AnySet) -> Type</name> + <name name="type" arity="1"/> <fsummary>Return the type of a set.</fsummary> - <type> - <v>AnySet = anyset()</v> - <v>Type = type()</v> - </type> <desc> <p>Returns the <seealso marker="#type">type</seealso> of an atomic, ordered or unordered set.</p> </desc> </func> <func> - <name>union(SetOfSets) -> Set</name> + <name name="union" arity="1"/> <fsummary>Return the union of a set of sets.</fsummary> - <type> - <v>Set = set()</v> - <v>SetOfSets = set_of_sets()</v> - </type> <desc> <p>Returns the <seealso marker="#union_n">union</seealso> of the - set of sets SetOfSets.</p> + set of sets <anno>SetOfSets</anno>.</p> </desc> </func> <func> - <name>union(Set1, Set2) -> Set3</name> + <name name="union" arity="2"/> <fsummary>Return the union of two sets.</fsummary> - <type> - <v>Set1 = Set2 = Set3 = set()</v> - </type> <desc> <p>Returns the <seealso marker="#union">union</seealso> of - Set1 and Set2.</p> + <anno>Set1</anno> and <anno>Set2</anno>.</p> </desc> </func> <func> - <name>union_of_family(Family) -> Set</name> + <name name="union_of_family" arity="1"/> <fsummary>Return the union of a family.</fsummary> - <type> - <v>Family = family()</v> - <v>Set = set()</v> - </type> <desc> <p>Returns the union of - the <seealso marker="#family">family</seealso> Family.</p> + the <seealso marker="#family">family</seealso> <anno>Family</anno>. + </p> <pre> 1> <input>F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),</input> <input>S = sofs:union_of_family(F),</input> @@ -1754,17 +1591,15 @@ images2(SetOfSets, BinRel) -> </desc> </func> <func> - <name>weak_relation(BinRel1) -> BinRel2</name> + <name name="weak_relation" arity="1"/> <fsummary>Return the weak relation corresponding to a given relation.</fsummary> - <type> - <v>BinRel1 = BinRel2 = binary_relation()</v> - </type> <desc> <p>Returns a subset S of the <seealso marker="#weak_relation">weak relation</seealso> W - corresponding to the binary relation BinRel1. Let F be the - <seealso marker="#field">field</seealso> of BinRel1. The + corresponding to the binary relation <anno>BinRel1</anno>. + Let F be the <seealso marker="#field">field</seealso> of + <anno>BinRel1</anno>. The subset S is defined so that x S y if x W y for some x in F and for some y in F.</p> <pre> diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml new file mode 100644 index 0000000000..98338b5ec2 --- /dev/null +++ b/lib/stdlib/doc/src/specs.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="latin1" ?> +<specs xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="../specs/specs_array.xml"/> + <xi:include href="../specs/specs_base64.xml"/> + <xi:include href="../specs/specs_beam_lib.xml"/> + <xi:include href="../specs/specs_binary.xml"/> + <xi:include href="../specs/specs_c.xml"/> + <xi:include href="../specs/specs_calendar.xml"/> + <xi:include href="../specs/specs_dets.xml"/> + <xi:include href="../specs/specs_dict.xml"/> + <xi:include href="../specs/specs_digraph.xml"/> + <xi:include href="../specs/specs_digraph_utils.xml"/> + <xi:include href="../specs/specs_epp.xml"/> + <xi:include href="../specs/specs_erl_eval.xml"/> + <xi:include href="../specs/specs_erl_expand_records.xml"/> + <xi:include href="../specs/specs_erl_id_trans.xml"/> + <xi:include href="../specs/specs_erl_internal.xml"/> + <xi:include href="../specs/specs_erl_lint.xml"/> + <xi:include href="../specs/specs_erl_parse.xml"/> + <xi:include href="../specs/specs_erl_pp.xml"/> + <xi:include href="../specs/specs_erl_scan.xml"/> + <xi:include href="../specs/specs_erl_tar.xml"/> + <xi:include href="../specs/specs_ets.xml"/> + <xi:include href="../specs/specs_file_sorter.xml"/> + <xi:include href="../specs/specs_filelib.xml"/> + <xi:include href="../specs/specs_filename.xml"/> + <xi:include href="../specs/specs_gb_sets.xml"/> + <xi:include href="../specs/specs_gb_trees.xml"/> + <xi:include href="../specs/specs_gen_event.xml"/> + <xi:include href="../specs/specs_gen_fsm.xml"/> + <xi:include href="../specs/specs_gen_server.xml"/> + <xi:include href="../specs/specs_io.xml"/> + <xi:include href="../specs/specs_io_lib.xml"/> + <xi:include href="../specs/specs_lib.xml"/> + <xi:include href="../specs/specs_lists.xml"/> + <xi:include href="../specs/specs_log_mf_h.xml"/> + <xi:include href="../specs/specs_math.xml"/> + <xi:include href="../specs/specs_ms_transform.xml"/> + <xi:include href="../specs/specs_orddict.xml"/> + <xi:include href="../specs/specs_ordsets.xml"/> + <xi:include href="../specs/specs_pg.xml"/> + <xi:include href="../specs/specs_pool.xml"/> + <xi:include href="../specs/specs_proc_lib.xml"/> + <xi:include href="../specs/specs_proplists.xml"/> + <xi:include href="../specs/specs_qlc.xml"/> + <xi:include href="../specs/specs_queue.xml"/> + <xi:include href="../specs/specs_random.xml"/> + <xi:include href="../specs/specs_re.xml"/> + <xi:include href="../specs/specs_regexp.xml"/> + <xi:include href="../specs/specs_sets.xml"/> + <xi:include href="../specs/specs_shell.xml"/> + <xi:include href="../specs/specs_shell_default.xml"/> + <xi:include href="../specs/specs_slave.xml"/> + <xi:include href="../specs/specs_sofs.xml"/> + <xi:include href="../specs/specs_string.xml"/> + <xi:include href="../specs/specs_supervisor.xml"/> + <xi:include href="../specs/specs_supervisor_bridge.xml"/> + <xi:include href="../specs/specs_sys.xml"/> + <xi:include href="../specs/specs_timer.xml"/> + <xi:include href="../specs/specs_unicode.xml"/> + <xi:include href="../specs/specs_win32reg.xml"/> + <xi:include href="../specs/specs_zip.xml"/> +</specs> diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml index de1b99a2d5..48867ffe72 100644 --- a/lib/stdlib/doc/src/string.xml +++ b/lib/stdlib/doc/src/string.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -38,65 +38,46 @@ </description> <funcs> <func> - <name>len(String) -> Length</name> + <name name="len" arity="1"/> <fsummary>Return the length of a string</fsummary> - <type> - <v>String = string()</v> - <v>Length = integer()</v> - </type> <desc> <p>Returns the number of characters in the string.</p> </desc> </func> <func> - <name>equal(String1, String2) -> bool()</name> + <name name="equal" arity="2"/> <fsummary>Test string equality</fsummary> - <type> - <v>String1 = String2 = string()</v> - </type> <desc> <p>Tests whether two strings are equal. Returns <c>true</c> if they are, otherwise <c>false</c>.</p> </desc> </func> <func> - <name>concat(String1, String2) -> String3</name> + <name name="concat" arity="2"/> <fsummary>Concatenate two strings</fsummary> - <type> - <v>String1 = String2 = String3 = string()</v> - </type> <desc> <p>Concatenates two strings to form a new string. Returns the new string.</p> </desc> </func> <func> - <name>chr(String, Character) -> Index</name> - <name>rchr(String, Character) -> Index</name> + <name name="chr" arity="2"/> + <name name="rchr" arity="2"/> <fsummary>Return the index of the first/last occurrence of<c>Character</c>in <c>String</c></fsummary> - <type> - <v>String = string()</v> - <v>Character = char()</v> - <v>Index = integer()</v> - </type> <desc> <p>Returns the index of the first/last occurrence of - <c>Character</c> in <c>String</c>. <c>0</c> is returned if <c>Character</c> does not + <c><anno>Character</anno></c> in <c><anno>String</anno></c>. <c>0</c> is returned if <c><anno>Character</anno></c> does not occur.</p> </desc> </func> <func> - <name>str(String, SubString) -> Index</name> - <name>rstr(String, SubString) -> Index</name> + <name name="str" arity="2"/> + <name name="rstr" arity="2"/> <fsummary>Find the index of a substring</fsummary> - <type> - <v>String = SubString = string()</v> - <v>Index = integer()</v> - </type> <desc> <p>Returns the position where the first/last occurrence of - <c>SubString</c> begins in <c>String</c>. <c>0</c> is returned if <c>SubString</c> - does not exist in <c>String</c>. + <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. <c>0</c> is returned if <c><anno>SubString</anno></c> + does not exist in <c><anno>String</anno></c>. For example:</p> <code type="none"> > string:str(" Hello Hello World World ", "Hello World"). @@ -104,17 +85,13 @@ </desc> </func> <func> - <name>span(String, Chars) -> Length </name> - <name>cspan(String, Chars) -> Length</name> + <name name="span" arity="2"/> + <name name="cspan" arity="2"/> <fsummary>Span characters at start of string</fsummary> - <type> - <v>String = Chars = string()</v> - <v>Length = integer()</v> - </type> <desc> <p>Returns the length of the maximum initial segment of - String, which consists entirely of characters from (not - from) Chars.</p> + <c><anno>String</anno></c>, which consists entirely of characters from (not + from) <c><anno>Chars</anno></c>.</p> <p>For example:</p> <code type="none"> > string:span("\t abcdef", " \t"). @@ -124,17 +101,13 @@ </desc> </func> <func> - <name>substr(String, Start) -> SubString</name> - <name>substr(String, Start, Length) -> Substring</name> + <name name="substr" arity="2"/> + <name name="substr" arity="3"/> <fsummary>Return a substring of <c>String</c></fsummary> - <type> - <v>String = SubString = string()</v> - <v>Start = Length = integer()</v> - </type> <desc> - <p>Returns a substring of <c>String</c>, starting at the - position <c>Start</c>, and ending at the end of the string or - at length <c>Length</c>.</p> + <p>Returns a substring of <c><anno>String</anno></c>, starting at the + position <c><anno>Start</anno></c>, and ending at the end of the string or + at length <c><anno>Length</anno></c>.</p> <p>For example:</p> <code type="none"> > substr("Hello World", 4, 5). @@ -142,15 +115,11 @@ </desc> </func> <func> - <name>tokens(String, SeparatorList) -> Tokens</name> + <name name="tokens" arity="2"/> <fsummary>Split string into tokens</fsummary> - <type> - <v>String = SeparatorList = string()</v> - <v>Tokens = [string()]</v> - </type> <desc> - <p>Returns a list of tokens in <c>String</c>, separated by the - characters in <c>SeparatorList</c>.</p> + <p>Returns a list of tokens in <c><anno>String</anno></c>, separated by the + characters in <c><anno>SeparatorList</anno></c>.</p> <p>For example:</p> <code type="none"> > tokens("abc defxxghix jkl", "x "). @@ -158,15 +127,11 @@ </desc> </func> <func> - <name>join(StringList, Separator) -> String</name> + <name name="join" arity="2"/> <fsummary>Join a list of strings with separator</fsummary> - <type> - <v>StringList = [string()]</v> - <v>Separator = string()</v> - </type> <desc> - <p>Returns a string with the elements of <c>StringList</c> - separated by the string in <c>Seperator</c>.</p> + <p>Returns a string with the elements of <c><anno>StringList</anno></c> + separated by the string in <c><anno>Separator</anno></c>.</p> <p>For example:</p> <code type="none"> > join(["one", "two", "three"], ", "). @@ -174,44 +139,30 @@ </desc> </func> <func> - <name>chars(Character, Number) -> String</name> - <name>chars(Character, Number, Tail) -> String</name> + <name name="chars" arity="2"/> + <name name="chars" arity="3"/> <fsummary>Returns a string consisting of numbers of characters</fsummary> - <type> - <v>Character = char()</v> - <v>Number = integer()</v> - <v>String = string()</v> - </type> <desc> - <p>Returns a string consisting of <c>Number</c> of characters - <c>Character</c>. Optionally, the string can end with the - string <c>Tail</c>.</p> + <p>Returns a string consisting of <c><anno>Number</anno></c> of characters + <c><anno>Character</anno></c>. Optionally, the string can end with the + string <c><anno>Tail</anno></c>.</p> </desc> </func> <func> - <name>copies(String, Number) -> Copies</name> + <name name="copies" arity="2"/> <fsummary>Copy a string</fsummary> - <type> - <v>String = Copies = string()</v> - <v>Number = integer()</v> - </type> <desc> - <p>Returns a string containing <c>String</c> repeated - <c>Number</c> times.</p> + <p>Returns a string containing <c><anno>String</anno></c> repeated + <c><anno>Number</anno></c> times.</p> </desc> </func> <func> - <name>words(String) -> Count</name> - <name>words(String, Character) -> Count</name> + <name name="words" arity="1"/> + <name name="words" arity="2"/> <fsummary>Count blank separated words</fsummary> - <type> - <v>String = string()</v> - <v>Character = char()</v> - <v>Count = integer()</v> - </type> <desc> - <p>Returns the number of words in <c>String</c>, separated by - blanks or <c>Character</c>.</p> + <p>Returns the number of words in <c><anno>String</anno></c>, separated by + blanks or <c><anno>Character</anno></c>.</p> <p>For example:</p> <code type="none"> > words(" Hello old boy!", $o). @@ -219,17 +170,12 @@ </desc> </func> <func> - <name>sub_word(String, Number) -> Word</name> - <name>sub_word(String, Number, Character) -> Word</name> + <name name="sub_word" arity="2"/> + <name name="sub_word" arity="3"/> <fsummary>Extract subword</fsummary> - <type> - <v>String = Word = string()</v> - <v>Character = char()</v> - <v>Number = integer()</v> - </type> <desc> - <p>Returns the word in position <c>Number</c> of <c>String</c>. - Words are separated by blanks or <c>Character</c>s.</p> + <p>Returns the word in position <c><anno>Number</anno></c> of <c><anno>String</anno></c>. + Words are separated by blanks or <c><anno>Character</anno></c>s.</p> <p>For example:</p> <code type="none"> > string:sub_word(" Hello old boy !",3,$o). @@ -237,19 +183,14 @@ </desc> </func> <func> - <name>strip(String) -> Stripped</name> - <name>strip(String, Direction) -> Stripped</name> - <name>strip(String, Direction, Character) -> Stripped</name> + <name name="strip" arity="1"/> + <name name="strip" arity="2"/> + <name name="strip" arity="3"/> <fsummary>Strip leading or trailing characters</fsummary> - <type> - <v>String = Stripped = string()</v> - <v>Direction = left | right | both</v> - <v>Character = char()</v> - </type> <desc> <p>Returns a string, where leading and/or trailing blanks or a - number of <c>Character</c> have been removed. - <c>Direction</c> can be <c>left</c>, <c>right</c>, or + number of <c><anno>Character</anno></c> have been removed. + <c><anno>Direction</anno></c> can be <c>left</c>, <c>right</c>, or <c>both</c> and indicates from which direction blanks are to be removed. The function <c>strip/1</c> is equivalent to <c>strip(String, both)</c>.</p> @@ -260,19 +201,14 @@ </desc> </func> <func> - <name>left(String, Number) -> Left</name> - <name>left(String, Number, Character) -> Left</name> + <name name="left" arity="2"/> + <name name="left" arity="3"/> <fsummary>Adjust left end of string</fsummary> - <type> - <v>String = Left = string()</v> - <v>Character = char</v> - <v>Number = integer()</v> - </type> <desc> - <p>Returns the <c>String</c> with the length adjusted in - accordance with <c>Number</c>. The left margin is - fixed. If the <c>length(String)</c> < <c>Number</c>, - <c>String</c> is padded with blanks or <c>Character</c>s.</p> + <p>Returns the <c><anno>String</anno></c> with the length adjusted in + accordance with <c><anno>Number</anno></c>. The left margin is + fixed. If the <c>length(<anno>String</anno>)</c> < <c><anno>Number</anno></c>, + <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p> <p>For example:</p> <code type="none"> > string:left("Hello",10,$.). @@ -280,19 +216,14 @@ </desc> </func> <func> - <name>right(String, Number) -> Right</name> - <name>right(String, Number, Character) -> Right</name> + <name name="right" arity="2"/> + <name name="right" arity="3"/> <fsummary>Adjust right end of string</fsummary> - <type> - <v>String = Right = string()</v> - <v>Character = char</v> - <v>Number = integer()</v> - </type> <desc> - <p>Returns the <c>String</c> with the length adjusted in - accordance with <c>Number</c>. The right margin is - fixed. If the length of <c>(String)</c> < <c>Number</c>, - <c>String</c> is padded with blanks or <c>Character</c>s.</p> + <p>Returns the <c><anno>String</anno></c> with the length adjusted in + accordance with <c><anno>Number</anno></c>. The right margin is + fixed. If the length of <c>(<anno>String</anno>)</c> < <c><anno>Number</anno></c>, + <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p> <p>For example:</p> <code type="none"> > string:right("Hello", 10, $.). @@ -300,32 +231,23 @@ </desc> </func> <func> - <name>centre(String, Number) -> Centered</name> - <name>centre(String, Number, Character) -> Centered</name> + <name name="centre" arity="2"/> + <name name="centre" arity="3"/> <fsummary>Center a string</fsummary> - <type> - <v>String = Centered = string()</v> - <v>Character = char</v> - <v>Number = integer()</v> - </type> <desc> - <p>Returns a string, where <c>String</c> is centred in the + <p>Returns a string, where <c><anno>String</anno></c> is centred in the string and surrounded by blanks or characters. The resulting - string will have the length <c>Number</c>.</p> + string will have the length <c><anno>Number</anno></c>.</p> </desc> </func> <func> - <name>sub_string(String, Start) -> SubString</name> - <name>sub_string(String, Start, Stop) -> SubString</name> + <name name="sub_string" arity="2"/> + <name name="sub_string" arity="3"/> <fsummary>Extract a substring</fsummary> - <type> - <v>String = SubString = string()</v> - <v>Start = Stop = integer()</v> - </type> <desc> - <p>Returns a substring of <c>String</c>, starting at the - position <c>Start</c> to the end of the string, or to and - including the <c>Stop</c> position.</p> + <p>Returns a substring of <c><anno>String</anno></c>, starting at the + position <c><anno>Start</anno></c> to the end of the string, or to and + including the <c><anno>Stop</anno></c> position.</p> <p>For example:</p> <code type="none"> sub_string("Hello World", 4, 8). @@ -383,15 +305,15 @@ sub_string("Hello World", 4, 8). </desc> </func> <func> - <name>to_lower(String) -> Result</name> - <name>to_lower(Char) -> CharResult</name> - <name>to_upper(String) -> Result</name> - <name>to_upper(Char) -> CharResult</name> + <name name="to_lower" arity="1" clause_i="1"/> + <name name="to_lower" arity="1" clause_i="2"/> + <name name="to_upper" arity="1" clause_i="1"/> + <name name="to_upper" arity="1" clause_i="2"/> <fsummary>Convert case of string (ISO/IEC 8859-1)</fsummary> - <type> - <v>String = Result = string()</v> - <v>Char = CharResult = integer()</v> - </type> + <type variable="String" name_i="1"/> + <type variable="Result" name_i="1"/> + <type variable="Char"/> + <type variable="CharResult"/> <desc> <p>The given string or character is case-converted. Note that the supported character set is ISO/IEC 8859-1 (a.k.a. Latin 1), diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index 45fa0847a8..ec607d6e4c 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2010</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -59,7 +59,6 @@ processes are started in order from left to right according to this list. When the supervisor terminates, it first terminates its child processes in reversed start order, from right to left.</p> - <p></p> <p>A supervisor can have one of the following <em>restart strategies</em>:</p> <list type="bulleted"> <item> @@ -83,11 +82,17 @@ supervisor, where all child processes are dynamically added instances of the same process type, i.e. running the same code.</p> - <p>The functions <c>terminate_child/2</c>, <c>delete_child/2</c> + <p>The functions <c>delete_child/2</c> and <c>restart_child/2</c> are invalid for <c>simple_one_for_one</c> supervisors and will return <c>{error,simple_one_for_one}</c> if the specified supervisor uses this restart strategy.</p> + <p>The function <c>terminate_child/2</c> can be used for + children under <c>simple_one_for_one</c> supervisors by + giving the child's <c>pid()</c> as the second argument. If + instead the child specification identifier is used, + <c>terminate_child/2</c> will return + <c>{error,simple_one_for_one}</c>.</p> </item> </list> <p>To prevent a supervisor from getting into an infinite loop of @@ -144,9 +149,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <p><c>Restart</c> defines when a terminated child process should be restarted. A <c>permanent</c> child process should always be restarted, a <c>temporary</c> child process should - never be restarted and a <c>transient</c> child process - should be restarted only if it terminates abnormally, i.e. - with another exit reason than <c>normal</c>.</p> + never be restarted (even when the supervisor's restart strategy + is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling's + death causes the temporary process to be terminated) and a + <c>transient</c> child process should be restarted only if + it terminates abnormally, i.e. with another exit reason + than <c>normal</c>.</p> </item> <item> <p><c>Shutdown</c> defines how a child process should be @@ -193,51 +201,81 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </item> </list> </section> + <datatypes> + <datatype> + <name name="child"/> + </datatype> + <datatype> + <name name="child_id"/> + <desc><p>Not a <c>pid()</c>.</p></desc> + </datatype> + <datatype> + <name name="child_spec"/> + </datatype> + <datatype> + <name name="mfargs"/> + <desc><p><c>A</c> (the argument list) has the value + <c>undefined</c> if <c>Restart</c> is <c>temporary</c>.</p> + </desc> + </datatype> + <datatype> + <name name="modules"/> + </datatype> + <datatype> + <name name="restart"/> + </datatype> + <datatype> + <name name="shutdown"/> + </datatype> + <datatype> + <name name="strategy"/> + </datatype> + <datatype> + <name name="sup_ref"/> + </datatype> + <datatype> + <name name="worker"/> + </datatype> + </datatypes> <funcs> <func> - <name>start_link(Module, Args) -> Result</name> - <name>start_link(SupName, Module, Args) -> Result</name> + <name name="start_link" arity="2"/> + <name name="start_link" arity="3"/> <fsummary>Create a supervisor process.</fsummary> - <type> - <v>SupName = {local,Name} | {global,Name}</v> - <v> Name = atom()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid}} | shutdown | term()</v> - </type> + <type name="startlink_ret"/> + <type name="startlink_err"/> + <type name="sup_name"/> <desc> <p>Creates a supervisor process as part of a supervision tree. The function will, among other things, ensure that the supervisor is linked to the calling process (its supervisor).</p> - <p>The created supervisor process calls <c>Module:init/1</c> to + <p>The created supervisor process calls <c><anno>Module</anno>:init/1</c> to find out about restart strategy, maximum restart frequency and child processes. To ensure a synchronized start-up procedure, <c>start_link/2,3</c> does not return until - <c>Module:init/1</c> has returned and all child processes + <c><anno>Module</anno>:init/1</c> has returned and all child processes have been started.</p> - <p>If <c>SupName={local,Name}</c> the supervisor is registered + <p>If <c><anno>SupName</anno>={local,Name}</c> the supervisor is registered locally as <c>Name</c> using <c>register/2</c>. If - <c>SupName={global,Name}</c> the supervisor is registered + <c><anno>SupName</anno>={global,Name}</c> the supervisor is registered globally as <c>Name</c> using <c>global:register_name/2</c>. If no name is provided, the supervisor is not registered.</p> - <p><c>Module</c> is the name of the callback module.</p> - <p><c>Args</c> is an arbitrary term which is passed as - the argument to <c>Module:init/1</c>.</p> + <p><c><anno>Module</anno></c> is the name of the callback module.</p> + <p><c><anno>Args</anno></c> is an arbitrary term which is passed as + the argument to <c><anno>Module</anno>:init/1</c>.</p> <p>If the supervisor and its child processes are successfully created (i.e. if all child process start functions return <c>{ok,Child}</c>, <c>{ok,Child,Info}</c>, or <c>ignore</c>) the function returns <c>{ok,Pid}</c>, where <c>Pid</c> is the pid of the supervisor. If there already exists a process - with the specified <c>SupName</c> the function returns + with the specified <c><anno>SupName</anno></c> the function returns <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is the pid of that process.</p> - <p>If <c>Module:init/1</c> returns <c>ignore</c>, this function + <p>If <c><anno>Module</anno>:init/1</c> returns <c>ignore</c>, this function returns <c>ignore</c> as well and the supervisor terminates with reason <c>normal</c>. - If <c>Module:init/1</c> fails or returns an incorrect value, + If <c><anno>Module</anno>:init/1</c> fails or returns an incorrect value, this function returns <c>{error,Term}</c> where <c>Term</c> is a term with information about the error, and the supervisor terminates with reason <c>Term</c>.</p> @@ -249,21 +287,15 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </desc> </func> <func> - <name>start_child(SupRef, ChildSpec) -> Result</name> + <name name="start_child" arity="2"/> <fsummary>Dynamically add a child process to a supervisor.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>ChildSpec = child_spec() | [term()]</v> - <v>Result = {ok,Child} | {ok,Child,Info} | {error,Error}</v> - <v> Child = pid() | undefined</v> - <v> Info = term()</v> - <v> Error = already_present | {already_started,Child} | term()</v> - </type> + <type name="child_spec"/> + <type name="startchild_ret"/> + <type name="startchild_err"/> <desc> <p>Dynamically adds a child specification to the supervisor - <c>SupRef</c> which starts the corresponding child process.</p> - <p><c>SupRef</c> can be:</p> + <c><anno>SupRef</anno></c> which starts the corresponding child process.</p> + <p><marker id="SupRef"><c><anno>SupRef</anno></c></marker> can be:</p> <list type="bulleted"> <item>the pid,</item> <item><c>Name</c>, if the supervisor is locally registered,</item> @@ -272,26 +304,26 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <item><c>{global,Name}</c>, if the supervisor is globally registered.</item> </list> - <p><c>ChildSpec</c> should be a valid child specification + <p><c><anno>ChildSpec</anno></c> should be a valid child specification (unless the supervisor is a <c>simple_one_for_one</c> supervisor, see below). The child process will be started by using the start function as defined in the child specification.</p> <p>If the case of a <c>simple_one_for_one</c> supervisor, the child specification defined in <c>Module:init/1</c> will - be used and <c>ChildSpec</c> should instead be an arbitrary - list of terms <c>List</c>. The child process will then be - started by appending <c>List</c> to the existing start + be used and <c><anno>ChildSpec</anno></c> should instead be an arbitrary + list of terms <c><anno>List</anno></c>. The child process will then be + started by appending <c><anno>List</anno></c> to the existing start function arguments, i.e. by calling - <c>apply(M, F, A++List)</c> where <c>{M,F,A}</c> is the start + <c>apply(M, F, A++<anno>List</anno>)</c> where <c>{M,F,A}</c> is the start function defined in the child specification.</p> <p>If there already exists a child specification with - the specified <c>Id</c>, <c>ChildSpec</c> is discarded and + the specified <c><anno>Id</anno></c>, <c><anno>ChildSpec</anno></c> is discarded and the function returns <c>{error,already_present}</c> or - <c>{error,{already_started,Child}}</c>, depending on if + <c>{error,{already_started,<anno>Child</anno>}}</c>, depending on if the corresponding child process is running or not.</p> - <p>If the child process start function returns <c>{ok,Child}</c> - or <c>{ok,Child,Info}</c>, the child specification and pid is + <p>If the child process start function returns <c>{ok,<anno>Child</anno>}</c> + or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the child specification and pid is added to the supervisor and the function returns the same value.</p> <p>If the child process start function returns <c>ignore</c>, @@ -306,138 +338,114 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </desc> </func> <func> - <name>terminate_child(SupRef, Id) -> Result</name> + <name name="terminate_child" arity="2"/> <fsummary>Terminate a child process belonging to a supervisor.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>Id = term()</v> - <v>Result = ok | {error,Error}</v> - <v> Error = not_found | simple_one_for_one</v> - </type> <desc> - <p>Tells the supervisor <c>SupRef</c> to terminate the child - process corresponding to the child specification identified - by <c>Id</c>. The process, if there is one, is terminated but - the child specification is kept by the supervisor. This means - that the child process may be later be restarted by - the supervisor. The child process can also be restarted - explicitly by calling <c>restart_child/2</c>. Use - <c>delete_child/2</c> to remove the child specification.</p> - <p>See <c>start_child/2</c> for a description of - <c>SupRef</c>.</p> + <p>Tells the supervisor <c><anno>SupRef</anno></c> to terminate the given + child.</p> + <p>If the supervisor is not <c>simple_one_for_one</c>, + <c><anno>Id</anno></c> must be the child specification identifier. The + process, if there is one, is terminated but the child + specification is kept by the supervisor. The child process + may later be restarted by the supervisor. The child process + can also be restarted explicitly by calling + <c>restart_child/2</c>. Use <c>delete_child/2</c> to remove + the child specification.</p> + <p>If the supervisor is <c>simple_one_for_one</c>, <c><anno>Id</anno></c> + must be the child process' <c>pid()</c>. I the specified + process is alive, but is not a child of the given + supervisor, the function will return + <c>{error,not_found}</c>. If the child specification + identifier is given instead instead of a <c>pid()</c>, the + function will return <c>{error,simple_one_for_one}</c>.</p> <p>If successful, the function returns <c>ok</c>. If there is - no child specification with the specified <c>Id</c>, - the function returns <c>{error,not_found}</c>.</p> + no child specification with the specified <c><anno>Id</anno></c>, the + function returns <c>{error,not_found}</c>.</p> + <p>See <c>start_child/2</c> for a description of + <c><anno>SupRef</anno></c>.</p> </desc> </func> <func> - <name>delete_child(SupRef, Id) -> Result</name> + <name name="delete_child" arity="2"/> <fsummary>Delete a child specification from a supervisor.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>Id = term()</v> - <v>Result = ok | {error,Error}</v> - <v> Error = running | not_found | simple_one_for_one</v> - </type> <desc> - <p>Tells the supervisor <c>SupRef</c> to delete the child - specification identified by <c>Id</c>. The corresponding child + <p>Tells the supervisor <c><anno>SupRef</anno></c> to delete the child + specification identified by <c><anno>Id</anno></c>. The corresponding child process must not be running, use <c>terminate_child/2</c> to terminate it.</p> - <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p> + <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of + <c>SupRef</c>.</p> <p>If successful, the function returns <c>ok</c>. If the child - specification identified by <c>Id</c> exists but + specification identified by <c><anno>Id</anno></c> exists but the corresponding child process is running, the function returns <c>{error,running}</c>. If the child specification - identified by <c>Id</c> does not exist, the function returns + identified by <c><anno>Id</anno></c> does not exist, the function returns <c>{error,not_found}</c>.</p> </desc> </func> <func> - <name>restart_child(SupRef, Id) -> Result</name> + <name name="restart_child" arity="2"/> <fsummary>Restart a terminated child process belonging to a supervisor.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>Id = term()</v> - <v>Result = {ok,Child} | {ok,Child,Info} | {error,Error}</v> - <v> Child = pid() | undefined</v> - <v> Error = running | not_found | simple_one_for_one | term()</v> - </type> <desc> - <p>Tells the supervisor <c>SupRef</c> to restart a child process + <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart a child process corresponding to the child specification identified by - <c>Id</c>. The child specification must exist and + <c><anno>Id</anno></c>. The child specification must exist and the corresponding child process must not be running.</p> - <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p> - <p>If the child specification identified by <c>Id</c> does not + <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of + <c>SupRef</c>.</p> + <p>If the child specification identified by <c><anno>Id</anno></c> does not exist, the function returns <c>{error,not_found}</c>. If the child specification exists but the corresponding process is already running, the function returns <c>{error,running}</c>.</p> - <p>If the child process start function returns <c>{ok,Child}</c> - or <c>{ok,Child,Info}</c>, the pid is added to the supervisor + <p>If the child process start function returns <c>{ok,<anno>Child</anno>}</c> + or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the pid is added to the supervisor and the function returns the same value.</p> <p>If the child process start function returns <c>ignore</c>, the pid remains set to <c>undefined</c> and the function returns <c>{ok,undefined}</c>.</p> <p>If the child process start function returns an error tuple or an erroneous value, or if it fails, the function returns - <c>{error,Error}</c> where <c>Error</c> is a term containing + <c>{error,<anno>Error</anno>}</c> where <c><anno>Error</anno></c> is a term containing information about the error.</p> </desc> </func> <func> - <name>which_children(SupRef) -> [{Id,Child,Type,Modules}]</name> + <name name="which_children" arity="1"/> <fsummary>Return information about all children specifications and child processes belonging to a supervisor.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>Id = term() | undefined</v> - <v>Child = pid() | undefined</v> - <v>Type = worker | supervisor</v> - <v>Modules = [Module] | dynamic</v> - <v> Module = atom()</v> - </type> <desc> <p>Returns a newly created list with information about all child specifications and child processes belonging to - the supervisor <c>SupRef</c>.</p> + the supervisor <c><anno>SupRef</anno></c>.</p> <p>Note that calling this function when supervising a large number of children under low memory conditions can cause an out of memory exception.</p> - <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p> + <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of + <c>SupRef</c>.</p> <p>The information given for each child specification/process is:</p> <list type="bulleted"> <item> - <p><c>Id</c> - as defined in the child specification or + <p><c><anno>Id</anno></c> - as defined in the child specification or <c>undefined</c> in the case of a <c>simple_one_for_one</c> supervisor.</p> </item> <item> - <p><c>Child</c> - the pid of the corresponding child + <p><c><anno>Child</anno></c> - the pid of the corresponding child process, or <c>undefined</c> if there is no such process.</p> </item> <item> - <p><c>Type</c> - as defined in the child specification.</p> + <p><c><anno>Type</anno></c> - as defined in the child specification.</p> </item> <item> - <p><c>Modules</c> - as defined in the child specification.</p> + <p><c><anno>Modules</anno></c> - as defined in the child specification.</p> </item> </list> </desc> </func> <func> - <name>count_children(SupRef) -> PropListOfCounts</name> + <name name="count_children" arity="1"/> <fsummary>Return counts for the number of childspecs, active children, supervisors and workers.</fsummary> - <type> - <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v> - <v> Name = Node = atom()</v> - <v>PropListOfCounts = [{specs, ChildSpecCount}, {active, ActiveProcessCount}, {supervisors, ChildSupervisorCount}, {workers, ChildWorkerCount}]</v> - </type> <desc> <p>Returns a property list (see <c>proplists</c>) containing the counts for each of the following elements of the supervisor's @@ -464,17 +472,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </desc> </func> <func> - <name>check_childspecs([ChildSpec]) -> Result</name> + <name name="check_childspecs" arity="1"/> <fsummary>Check if children specifications are syntactically correct.</fsummary> - <type> - <v>ChildSpec = child_spec()</v> - <v>Result = ok | {error,Error}</v> - <v> Error = term()</v> - </type> <desc> <p>This function takes a list of child specification as argument and returns <c>ok</c> if all of them are syntactically - correct, or <c>{error,Error}</c> otherwise.</p> + correct, or <c>{error,<anno>Error</anno>}</c> otherwise.</p> </desc> </func> </funcs> @@ -491,9 +494,9 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <type> <v>Args = term()</v> <v>Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore</v> - <v> RestartStrategy = one_for_all | one_for_one | rest_for_one | simple_one_for_one</v> - <v> MaxR = MaxT = int()>=0</v> - <v> ChildSpec = child_spec()</v> + <v> RestartStrategy = <seealso marker="#type-strategy">strategy()</seealso></v> + <v> MaxR = MaxT = integer()>=0</v> + <v> ChildSpec = <seealso marker="#type-child_spec">child_spec()</seealso></v> </type> <desc> <p>Whenever a supervisor is started using diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml index cbd0d9230b..c1a5e7947f 100644 --- a/lib/stdlib/doc/src/supervisor_bridge.xml +++ b/lib/stdlib/doc/src/supervisor_bridge.xml @@ -50,46 +50,37 @@ </description> <funcs> <func> - <name>start_link(Module, Args) -> Result</name> - <name>start_link(SupBridgeName, Module, Args) -> Result</name> + <name name="start_link" arity="2"/> + <name name="start_link" arity="3"/> <fsummary>Create a supervisor bridge process.</fsummary> - <type> - <v>SupBridgeName = {local,Name} | {global,Name}</v> - <v> Name = atom()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> <desc> <p>Creates a supervisor_bridge process, linked to the calling - process, which calls <c>Module:init/1</c> to start the subsystem. + process, which calls <c><anno>Module</anno>:init/1</c> to start the subsystem. To ensure a synchronized start-up procedure, this function does - not return until <c>Module:init/1</c> has returned.</p> - <p>If <c>SupBridgeName={local,Name}</c> the supervisor_bridge is - registered locally as <c>Name</c> using <c>register/2</c>. - If <c>SupBridgeName={global,Name}</c> the supervisor_bridge is - registered globally as <c>Name</c> using + not return until <c><anno>Module</anno>:init/1</c> has returned.</p> + <p>If <c><anno>SupBridgeName</anno>={local,<anno>Name</anno>}</c> the supervisor_bridge is + registered locally as <c><anno>Name</anno></c> using <c>register/2</c>. + If <c><anno>SupBridgeName</anno>={global,<anno>Name</anno>}</c> the supervisor_bridge is + registered globally as <c><anno>Name</anno></c> using <c>global:register_name/2</c>. If no name is provided, the supervisor_bridge is not registered. If there already exists a process with the specified - <c>SupBridgeName</c> the function returns - <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is the pid + <c><anno>SupBridgeName</anno></c> the function returns + <c>{error,{already_started,<anno>Pid</anno>}}</c>, where <c><anno>Pid</anno></c> is the pid of that process.</p> - <p><c>Module</c> is the name of the callback module.</p> - <p><c>Args</c> is an arbitrary term which is passed as the argument - to <c>Module:init/1</c>.</p> + <p><c><anno>Module</anno></c> is the name of the callback module.</p> + <p><c><anno>Args</anno></c> is an arbitrary term which is passed as the argument + to <c><anno>Module</anno>:init/1</c>.</p> <p>If the supervisor_bridge and the subsystem are successfully - started the function returns <c>{ok,Pid}</c>, where <c>Pid</c> is + started the function returns <c>{ok,<anno>Pid</anno>}</c>, where <c><anno>Pid</anno></c> is is the pid of the supervisor_bridge.</p> - <p>If <c>Module:init/1</c> returns <c>ignore</c>, this function + <p>If <c><anno>Module</anno>:init/1</c> returns <c>ignore</c>, this function returns <c>ignore</c> as well and the supervisor_bridge terminates with reason <c>normal</c>. - If <c>Module:init/1</c> fails or returns an error tuple or an - incorrect value, this function returns <c>{error,Term}</c> where - <c>Term</c> is a term with information about the error, and - the supervisor_bridge terminates with reason <c>Term</c>.</p> + If <c><anno>Module</anno>:init/1</c> fails or returns an error tuple or an + incorrect value, this function returns <c>{error,<anno>Error</anno>r}</c> where + <c><anno>Error</anno></c> is a term with information about the error, and + the supervisor_bridge terminates with reason <c><anno>Error</anno></c>.</p> </desc> </func> </funcs> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index efa8922a9d..073faf2df2 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -39,24 +39,12 @@ <p>Functions used for implementation of processes should also understand system messages such as debugging messages and code change. These functions must be used to implement the use of system messages for a process; either directly, or through standard behaviours, such as <c>gen_server</c>.</p> - <p>The following types are used in the functions defined below:</p> - <list type="bulleted"> - <item> - <p><c>Name = pid() | atom() | {global, atom()}</c></p> - </item> - <item> - <p><c>Timeout = int() >= 0 | infinity</c></p> - </item> - <item> - <p><c>system_event() = {in, Msg} | {in, Msg, From} | {out, Msg, To} | term()</c></p> - </item> - </list> <p>The default timeout is 5000 ms, unless otherwise specified. The <c>timeout</c> defines the time period to wait for the process to respond to a request. If the process does not respond, the function evaluates <c>exit({timeout, {M, F, A}})</c>. </p> - <p>The functions make reference to a debug structure. + <p><marker id="dbg_opt"/>The functions make reference to a debug structure. The debug structure is a list of <c>dbg_opt()</c>. <c>dbg_opt()</c> is an internal data type used by the <c>handle_system_msg/6</c> function. No debugging is performed if it is an empty list. @@ -113,20 +101,31 @@ own system events. It is always up to the process itself to format these events.</p> </section> + <datatypes> + <datatype> + <name name="name"/> + </datatype> + <datatype> + <name name="system_event"/> + </datatype> + <datatype> + <name name="dbg_opt"/> + <desc><p>See <seealso marker="#dbg_opt">above</seealso>.</p></desc> + </datatype> + <datatype> + <name name="dbg_fun"/> + </datatype> + </datatypes> <funcs> <func> - <name>log(Name,Flag)</name> - <name>log(Name,Flag,Timeout) -> ok | {ok, [system_event()]}</name> + <name name="log" arity="2"/> + <name name="log" arity="3"/> <fsummary>Log system events in memory</fsummary> - <type> - <v>Flag = true | {true, N} | false | get | print</v> - <v>N = integer() > 0</v> - </type> <desc> <p>Turns the logging of system events On or Off. If On, a - maximum of <c>N</c> events are kept in the - debug structure (the default is 10). If <c>Flag</c> is <c>get</c>, a list of all - logged events is returned. If <c>Flag</c> is <c>print</c>, the + maximum of <c><anno>N</anno></c> events are kept in the + debug structure (the default is 10). If <c><anno>Flag</anno></c> is <c>get</c>, a list of all + logged events is returned. If <c><anno>Flag</anno></c> is <c>print</c>, the logged events are printed to <c>standard_io</c>. The events are formatted with a function that is defined by the process that generated the event (with a call to @@ -134,13 +133,9 @@ </desc> </func> <func> - <name>log_to_file(Name,Flag)</name> - <name>log_to_file(Name,Flag,Timeout) -> ok | {error, open_file}</name> + <name name="log_to_file" arity="2"/> + <name name="log_to_file" arity="3"/> <fsummary>Log system events to the specified file</fsummary> - <type> - <v>Flag = FileName | false</v> - <v>FileName = string()</v> - </type> <desc> <p>Enables or disables the logging of all system events in textual format to the file. The events are formatted with a function that is @@ -149,27 +144,18 @@ </desc> </func> <func> - <name>statistics(Name,Flag)</name> - <name>statistics(Name,Flag,Timeout) -> ok | {ok, Statistics} </name> + <name name="statistics" arity="2"/> + <name name="statistics" arity="3"/> <fsummary>Enable or disable the collections of statistics</fsummary> - <type> - <v>Flag = true | false | get</v> - <v>Statistics = [{start_time, {Date1, Time1}}, {current_time, {Date, Time2}}, {reductions, integer()}, {messages_in, integer()}, {messages_out, integer()}]</v> - <v>Date1 = Date2 = {Year, Month, Day}</v> - <v>Time1 = Time2 = {Hour, Min, Sec}</v> - </type> <desc> - <p>Enables or disables the collection of statistics. If <c>Flag</c> is + <p>Enables or disables the collection of statistics. If <c><anno>Flag</anno></c> is <c>get</c>, the statistical collection is returned.</p> </desc> </func> <func> - <name>trace(Name,Flag)</name> - <name>trace(Name,Flag,Timeout) -> void()</name> + <name name="trace" arity="2"/> + <name name="trace" arity="3"/> <fsummary>Print all system events on <c>standard_io</c></fsummary> - <type> - <v>Flag = boolean()</v> - </type> <desc> <p>Prints all system events on <c>standard_io</c>. The events are formatted with a function that is defined by the process that @@ -178,8 +164,8 @@ </desc> </func> <func> - <name>no_debug(Name)</name> - <name>no_debug(Name,Timeout) -> void()</name> + <name name="no_debug" arity="1"/> + <name name="no_debug" arity="2"/> <fsummary>Turn off debugging</fsummary> <desc> <p>Turns off all debugging for the process. This includes @@ -188,8 +174,8 @@ </desc> </func> <func> - <name>suspend(Name)</name> - <name>suspend(Name,Timeout) -> void()</name> + <name name="suspend" arity="1"/> + <name name="suspend" arity="2"/> <fsummary>Suspend the process</fsummary> <desc> <p>Suspends the process. When the process is suspended, it @@ -198,49 +184,37 @@ </desc> </func> <func> - <name>resume(Name)</name> - <name>resume(Name,Timeout) -> void()</name> + <name name="resume" arity="1"/> + <name name="resume" arity="2"/> <fsummary>Resume a suspended process</fsummary> <desc> <p>Resumes a suspended process.</p> </desc> </func> <func> - <name>change_code(Name, Module, OldVsn, Extra)</name> - <name>change_code(Name, Module, OldVsn, Extra, Timeout) -> ok | {error, Reason}</name> + <name name="change_code" arity="4"/> + <name name="change_code" arity="5"/> <fsummary>Send the code change system message to the process</fsummary> - <type> - <v>OldVsn = undefined | term()</v> - <v>Module = atom()</v> - <v>Extra = term()</v> - </type> <desc> <p>Tells the process to change code. The process must be - suspended to handle this message. The <c>Extra</c> argument is + suspended to handle this message. The <c><anno>Extra</anno></c> argument is reserved for each process to use as its own. The function - <c>Mod:system_code_change/4</c> is called. <c>OldVsn</c> is - the old version of the <c>Module</c>.</p> + <c><anno>Module</anno>:system_code_change/4</c> is called. <c><anno>OldVsn</anno></c> is + the old version of the <c><anno>Module</anno></c>.</p> </desc> </func> <func> - <name>get_status(Name)</name> - <name>get_status(Name,Timeout) -> {status, Pid, {module, Mod}, [PDict, SysState, Parent, Dbg, Misc]}</name> + <name name="get_status" arity="1"/> + <name name="get_status" arity="2"/> <fsummary>Get the status of the process</fsummary> - <type> - <v>PDict = [{Key, Value}]</v> - <v>SysState = running | suspended</v> - <v>Parent = pid()</v> - <v>Dbg = [dbg_opt()]</v> - <v>Misc = term()</v> - </type> <desc> <p>Gets the status of the process.</p> - <p>The value of <c>Misc</c> varies for different types of + <p>The value of <c><anno>Misc</anno></c> varies for different types of processes. For example, a <c>gen_server</c> process returns the callback module's state, and a <c>gen_fsm</c> process returns information such as its current state name. Callback modules for <c>gen_server</c> and <c>gen_fsm</c> can also - customise the value of <c>Misc</c> by exporting + customise the value of <c><anno>Misc</anno></c> by exporting a <c>format_status/2</c> function that contributes module-specific information; see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso> @@ -249,17 +223,9 @@ </desc> </func> <func> - <name>install(Name,{Func,FuncState})</name> - <name>install(Name,{Func,FuncState},Timeout)</name> + <name name="install" arity="2"/> + <name name="install" arity="3"/> <fsummary>Install a debug function in the process</fsummary> - <type> - <v>Func = dbg_fun()</v> - <v>dbg_fun() = fun(FuncState, Event, ProcState) -> done | NewFuncState</v> - <v>FuncState = term()</v> - <v>Event = system_event()</v> - <v>ProcState = term()</v> - <v>NewFuncState = term()</v> - </type> <desc> <p>This function makes it possible to install other debug functions than the ones defined above. An example of such a @@ -267,22 +233,19 @@ special event and performs some action when the event is generated. This could, for example, be turning on low level tracing. </p> - <p><c>Func</c> is called whenever a system event is + <p><c><anno>Func</anno></c> is called whenever a system event is generated. This function should return <c>done</c>, or a new func state. In the first case, the function is removed. It is removed if the function fails.</p> </desc> </func> <func> - <name>remove(Name,Func)</name> - <name>remove(Name,Func,Timeout) -> void()</name> + <name name="remove" arity="2"/> + <name name="remove" arity="3"/> <fsummary>Remove a debug function from the process</fsummary> - <type> - <v>Func = dbg_fun()</v> - </type> <desc> <p>Removes a previously installed debug function from the - process. <c>Func</c> must be the same as previously + process. <c><anno>Func</anno></c> must be the same as previously installed.</p> </desc> </func> @@ -296,86 +259,65 @@ </section> <funcs> <func> - <name>debug_options(Options) -> [dbg_opt()]</name> + <name name="debug_options" arity="1"/> <fsummary>Convert a list of options to a debug structure</fsummary> - <type> - <v>Options = [Opt]</v> - <v>Opt = trace | log | statistics | {log_to_file, FileName} | {install, {Func, FuncState}}</v> - <v>Func = dbg_fun()</v> - <v>FuncState = term()</v> - </type> <desc> <p>This function can be used by a process that initiates a debug structure from a list of options. The values of the - <c>Opt</c> argument are the same as the corresponding + <c><anno>Opt</anno></c> argument are the same as the corresponding functions.</p> </desc> </func> <func> - <name>get_debug(Item,Debug,Default) -> term()</name> + <name name="get_debug" arity="3"/> <fsummary>Get the data associated with a debug option</fsummary> - <type> - <v>Item = log | statistics</v> - <v>Debug = [dbg_opt()]</v> - <v>Default = term()</v> - </type> <desc> - <p>This function gets the data associated with a debug option. <c>Default</c> is returned if the - <c>Item</c> is not found. Can be + <p>This function gets the data associated with a debug option. <c><anno>Default</anno></c> is returned if the + <c><anno>Item</anno></c> is not found. Can be used by the process to retrieve debug data for printing before it terminates.</p> </desc> </func> <func> - <name>handle_debug([dbg_opt()],FormFunc,Extra,Event) -> [dbg_opt()]</name> + <name name="handle_debug" arity="4"/> <fsummary>Generate a system event</fsummary> - <type> - <v>FormFunc = dbg_fun()</v> - <v>Extra = term()</v> - <v>Event = system_event()</v> - </type> <desc> - <p>This function is called by a process when it generates a system event. <c>FormFunc</c> is a formatting function which is called as <c>FormFunc(Device, Event, Extra)</c> in order to print the events, which is necessary if tracing is activated. <c>Extra</c> is any - extra information which the process needs in the format function, for example the name of the process.</p> + <p>This function is called by a process when it generates a + system event. <c><anno>FormFunc</anno></c> is a formatting + function which is called as <c><anno>FormFunc</anno>(Device, + <anno>Event</anno>, <anno>Extra</anno>)</c> in order to print + the events, which is necessary if tracing is activated. + <c><anno>Extra</anno></c> is any extra information which the + process needs in the format function, for example the name + of the process.</p> </desc> </func> <func> - <name>handle_system_msg(Msg,From,Parent,Module,Debug,Misc)</name> + <name name="handle_system_msg" arity="6"/> <fsummary>Take care of system messages</fsummary> - <type> - <v>Msg = term()</v> - <v>From = pid()</v> - <v>Parent = pid()</v> - <v>Module = atom()</v> - <v>Debug = [dbg_opt()]</v> - <v>Misc = term()</v> - </type> <desc> <p>This function is used by a process module that wishes to take care of system - messages. The process receives a <c>{system, From, Msg}</c> - message and passes the <c>Msg</c> and <c>From</c> to this + messages. The process receives a <c>{system, <anno>From</anno>, <anno>Msg</anno>}</c> + message and passes the <c><anno>Msg</anno></c> and <c><anno>From</anno></c> to this function. </p> <p>This function <em>never</em> returns. It calls the function - <c>Module:system_continue(Parent, NDebug, Misc)</c> where the + <c><anno>Module</anno>:system_continue(<anno>Parent</anno>, NDebug, <anno>Misc</anno>)</c> where the process continues the execution, or - <c>Module:system_terminate(Reason, Parent, Debug, Misc)</c> if - the process should terminate. The <c>Module</c> must export + <c><anno>Module</anno>:system_terminate(Reason, <anno>Parent</anno>, <anno>Debug</anno>, <anno>Misc</anno>)</c> if + the process should terminate. The <c><anno>Module</anno></c> must export <c>system_continue/3</c>, <c>system_terminate/4</c>, and <c>system_code_change/4</c> (see below). </p> - <p>The <c>Misc</c> argument can be used to save internal data + <p>The <c><anno>Misc</anno></c> argument can be used to save internal data in a process, for example its state. It is sent to - <c>Module:system_continue/3</c> or - <c>Module:system_terminate/4</c></p> + <c><anno>Module</anno>:system_continue/3</c> or + <c><anno>Module</anno>:system_terminate/4</c></p> </desc> </func> <func> - <name>print_log(Debug) -> void()</name> + <name name="print_log" arity="1"/> <fsummary>Print the logged events in the debug structure</fsummary> - <type> - <v>Debug = [dbg_opt()]</v> - </type> <desc> <p>Prints the logged system events in the debug structure using <c>FormFunc</c> as defined when the event was @@ -383,11 +325,11 @@ </desc> </func> <func> - <name>Mod:system_continue(Parent, Debug, Misc)</name> + <name>Mod:system_continue(Parent, Debug, Misc) -> none()</name> <fsummary>Called when the process should continue its execution</fsummary> <type> <v>Parent = pid()</v> - <v>Debug = [dbg_opt()]</v> + <v>Debug = [<seealso marker="#type-dbg_opt">dbg_opt()</seealso>]</v> <v>Misc = term()</v> </type> <desc> @@ -397,12 +339,12 @@ </desc> </func> <func> - <name>Mod:system_terminate(Reason, Parent, Debug, Misc)</name> + <name>Mod:system_terminate(Reason, Parent, Debug, Misc) -> none()</name> <fsummary>Called when the process should terminate</fsummary> <type> <v>Reason = term()</v> <v>Parent = pid()</v> - <v>Debug = [dbg_opt()]</v> + <v>Debug = [<seealso marker="#type-dbg_opt">dbg_opt()</seealso>]</v> <v>Misc = term()</v> </type> <desc> diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml index cae655f801..0c1e398dc4 100644 --- a/lib/stdlib/doc/src/timer.xml +++ b/lib/stdlib/doc/src/timer.xml @@ -49,9 +49,19 @@ as requested. </p> </description> + <datatypes> + <datatype> + <name name="time"/> + <desc><p>Time in milliseconds.</p></desc> + </datatype> + <datatype> + <name name="tref"/> + <desc><p>A timer reference.</p></desc> + </datatype> + </datatypes> <funcs> <func> - <name>start() -> ok</name> + <name name="start" arity="0"/> <fsummary>Start a global timer server (named <c>timer_server</c>).</fsummary> <desc> <p>Starts the timer server. Normally, the server does not need @@ -62,214 +72,185 @@ </desc> </func> <func> - <name>apply_after(Time, Module, Function, Arguments) -> {ok, Tref} | {error, Reason}</name> + <name name="apply_after" arity="4"/> <fsummary>Apply <c>Module:Function(Arguments)</c>after a specified <c>Time</c>.</fsummary> - <type> - <v>Time = integer() in Milliseconds</v> - <v>Module = Function = atom()</v> - <v>Arguments = [term()]</v> - </type> <desc> - <p>Evaluates <c>apply(M, F, A)</c> after <c>Time</c> amount of time - has elapsed. Returns <c>{ok, TRef}</c>, or <c>{error, Reason}</c>.</p> + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> after <c><anno>Time</anno></c> amount of time + has elapsed. Returns <c>{ok, <anno>TRef</anno>}</c>, or <c>{error, <anno>Reason</anno>}</c>.</p> </desc> </func> <func> - <name>send_after(Time, Pid, Message) -> {ok, TRef} | {error,Reason}</name> - <name>send_after(Time, Message) -> {ok, TRef} | {error,Reason}</name> + <name name="send_after" arity="2"/> + <name name="send_after" arity="3"/> <fsummary>Send <c>Message</c>to <c>Pid</c>after a specified <c>Time</c>.</fsummary> - <type> - <v>Time = integer() in Milliseconds</v> - <v>Pid = pid() | atom()</v> - <v>Message = term()</v> - <v>Result = {ok, TRef} | {error, Reason}</v> - </type> <desc> - <p></p> + <p> <taglist> <tag><c>send_after/3</c></tag> <item> - <p>Evaluates <c>Pid ! Message</c> after <c>Time</c> amount - of time has elapsed. (<c>Pid</c> can also be an atom of a - registered name.) Returns <c>{ok, TRef}</c>, or - <c>{error, Reason}</c>.</p> + <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> after <c><anno>Time</anno></c> amount + of time has elapsed. (<c><anno>Pid</anno></c> can also be an atom of a + registered name.) Returns <c>{ok, <anno>TRef</anno>}</c>, or + <c>{error, <anno>Reason</anno>}</c>.</p> </item> <tag><c>send_after/2</c></tag> <item> - <p>Same as <c>send_after(Time, self(), Message)</c>.</p> + <p>Same as <c>send_after(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p> </item> </taglist> + </p> </desc> </func> <func> - <name>exit_after(Time, Pid, Reason1) -> {ok, TRef} | {error,Reason2}</name> - <name>exit_after(Time, Reason1) -> {ok, TRef} | {error,Reason2}</name> - <name>kill_after(Time, Pid)-> {ok, TRef} | {error,Reason2}</name> - <name>kill_after(Time) -> {ok, TRef} | {error,Reason2}</name> + <name name="kill_after" arity="1"/> + <name name="kill_after" arity="2"/> + <name name="exit_after" arity="2"/> + <name name="exit_after" arity="3"/> <fsummary>Send an exit signal with <c>Reason</c>after a specified <c>Time</c>.</fsummary> - <type> - <v>Time = integer() in milliseconds</v> - <v>Pid = pid() | atom()</v> - <v>Reason1 = Reason2 = term()</v> - </type> <desc> - <p></p> + <p> <taglist> <tag><c>exit_after/3</c></tag> <item> - <p>Send an exit signal with reason <c>Reason1</c> to Pid - <c>Pid</c>. Returns <c>{ok, TRef}</c>, or - <c>{error, Reason2}</c>.</p> + <p>Send an exit signal with reason <c><anno>Reason1</anno></c> to Pid + <c><anno>Pid</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>, or + <c>{error, <anno>Reason2</anno>}</c>.</p> </item> <tag><c>exit_after/2</c></tag> <item> - <p>Same as <c>exit_after(Time, self(), Reason1)</c>. </p> + <p>Same as <c>exit_after(<anno>Time</anno>, self(), <anno>Reason1</anno>)</c>. </p> </item> <tag><c>kill_after/2</c></tag> <item> - <p>Same as <c>exit_after(Time, Pid, kill)</c>. </p> + <p>Same as <c>exit_after(<anno>Time</anno>, <anno>Pid</anno>, kill)</c>. </p> </item> <tag><c>kill_after/1</c></tag> <item> - <p>Same as <c>exit_after(Time, self(), kill)</c>. </p> + <p>Same as <c>exit_after(<anno>Time</anno>, self(), kill)</c>. </p> </item> </taglist> + </p> </desc> </func> <func> - <name>apply_interval(Time, Module, Function, Arguments) -> {ok, TRef} | {error, Reason}</name> + <name name="apply_interval" arity="4"/> <fsummary>Evaluate <c>Module:Function(Arguments)</c>repeatedly at intervals of <c>Time</c>.</fsummary> - <type> - <v>Time = integer() in milliseconds</v> - <v>Module = Function = atom()</v> - <v>Arguments = [term()]</v> - </type> <desc> - <p>Evaluates <c>apply(Module, Function, Arguments)</c> repeatedly at - intervals of <c>Time</c>. Returns <c>{ok, TRef}</c>, or - <c>{error, Reason}</c>.</p> + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> repeatedly at + intervals of <c><anno>Time</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>, or + <c>{error, <anno>Reason</anno>}</c>.</p> </desc> </func> <func> - <name>send_interval(Time, Pid, Message) -> {ok, TRef} | {error, Reason}</name> - <name>send_interval(Time, Message) -> {ok, TRef} | {error, Reason}</name> + <name name="send_interval" arity="2"/> + <name name="send_interval" arity="3"/> <fsummary>Send <c>Message</c>repeatedly at intervals of <c>Time</c>.</fsummary> - <type> - <v>Time = integer() in milliseconds</v> - <v>Pid = pid() | atom()</v> - <v>Message = term()</v> - <v>Reason = term()</v> - </type> <desc> - <p></p> + <p> <taglist> <tag><c>send_interval/3</c></tag> <item> - <p>Evaluates <c>Pid ! Message</c> repeatedly after <c>Time</c> - amount of time has elapsed. (<c>Pid</c> can also be an atom of - a registered name.) Returns <c>{ok, TRef}</c> or - <c>{error, Reason}</c>.</p> + <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> repeatedly after <c><anno>Time</anno></c> + amount of time has elapsed. (<c><anno>Pid</anno></c> can also be an atom of + a registered name.) Returns <c>{ok, <anno>TRef</anno>}</c> or + <c>{error, <anno>Reason</anno>}</c>.</p> </item> <tag><c>send_interval/2</c></tag> <item> - <p>Same as <c>send_interval(Time, self(), Message)</c>.</p> + <p>Same as <c>send_interval(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p> </item> </taglist> + </p> </desc> </func> <func> - <name>cancel(TRef) -> {ok, cancel} | {error, Reason}</name> + <name name="cancel" arity="1"/> <fsummary>Cancel a previously requested timeout identified by <c>TRef</c>.</fsummary> <desc> - <p>Cancels a previously requested timeout. <c>TRef</c> is a unique + <p>Cancels a previously requested timeout. <c><anno>TRef</anno></c> is a unique timer reference returned by the timer function in question. Returns - <c>{ok, cancel}</c>, or <c>{error, Reason}</c> when <c>TRef</c> + <c>{ok, cancel}</c>, or <c>{error, <anno>Reason</anno>}</c> when <c><anno>TRef</anno></c> is not a timer reference.</p> </desc> </func> <func> - <name>sleep(Time) -> ok</name> + <name name="sleep" arity="1"/> <fsummary>Suspend the calling process for <c>Time</c>amount of milliseconds.</fsummary> - <type> - <v>Time = integer() in milliseconds or the atom infinity</v> - </type> <desc> - <p>Suspends the process calling this function for <c>Time</c> amount + <p>Suspends the process calling this function for <c><anno>Time</anno></c> amount of milliseconds and then returns <c>ok</c>, or suspend the process - forever if <c>Time</c> is the atom <c>infinity</c>. Naturally, this + forever if <c><anno>Time</anno></c> is the atom <c>infinity</c>. Naturally, this function does <em>not</em> return immediately.</p> </desc> </func> <func> - <name>tc(Module, Function, Arguments) -> {Time, Value}</name> - <name>tc(Fun, Arguments) -> {Time, Value}</name> + <name name="tc" arity="1"/> + <name name="tc" arity="2"/> + <name name="tc" arity="3"/> <fsummary>Measure the real time it takes to evaluate <c>apply(Module, Function, Arguments)</c> or <c>apply(Fun, Arguments)</c></fsummary> - <type> - <v>Module = Function = atom()</v> - <v>Fun = fun()</v> - <v>Arguments = [term()]</v> - <v>Time = integer() in microseconds</v> - <v>Value = term()</v> - </type> + <type_desc variable="Time">In microseconds</type_desc> <desc> - <p></p> + <p> <taglist> <tag><c>tc/3</c></tag> <item> - <p>Evaluates <c>apply(Module, Function, Arguments)</c> and measures - the elapsed real time as reported by <c>now/0</c>. - Returns <c>{Time, Value}</c>, where - <c>Time</c> is the elapsed real time in <em>microseconds</em>, - and <c>Value</c> is what is returned from the apply.</p> + <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> and measures + the elapsed real time as reported by <c>os:timestamp/0</c>. + Returns <c>{<anno>Time</anno>, <anno>Value</anno>}</c>, where + <c><anno>Time</anno></c> is the elapsed real time in <em>microseconds</em>, + and <c><anno>Value</anno></c> is what is returned from the apply.</p> </item> <tag><c>tc/2</c></tag> <item> - <p>Evaluates <c>apply(Fun, Arguments)</c>. Otherwise works + <p>Evaluates <c>apply(<anno>Fun</anno>, <anno>Arguments</anno>)</c>. Otherwise works like <c>tc/3</c>.</p> </item> + <tag><c>tc/1</c></tag> + <item> + <p>Evaluates <c><anno>Fun</anno>()</c>. Otherwise works like <c>tc/2</c>.</p> + </item> + </taglist> + </p> </desc> </func> <func> - <name>now_diff(T2, T1) -> Tdiff</name> + <name name="now_diff" arity="2"/> <fsummary>Calculate time difference between <c>now/0</c>timestamps</fsummary> - <type> - <v>T1 = T2 = {MegaSecs, Secs, MicroSecs}</v> - <v>Tdiff = MegaSecs = Secs = MicroSecs = integer()</v> - </type> + <type_desc variable="Tdiff">In microseconds</type_desc> <desc> - <p>Calculates the time difference <c>Tdiff = T2 - T1</c> in - <em>microseconds</em>, where <c>T1</c> and <c>T2</c> probably + <p>Calculates the time difference <c><anno>Tdiff</anno> = <anno>T2</anno> - <anno>T1</anno></c> in + <em>microseconds</em>, where <c><anno>T1</anno></c> and <c><anno>T2</anno></c> probably are timestamp tuples returned from <c>erlang:now/0</c>.</p> </desc> </func> <func> - <name>seconds(Seconds) -> Milliseconds</name> + <name name="seconds" arity="1"/> <fsummary>Convert <c>Seconds</c>to <c>Milliseconds</c>.</fsummary> <desc> - <p>Returns the number of milliseconds in <c>Seconds</c>.</p> + <p>Returns the number of milliseconds in <c><anno>Seconds</anno></c>.</p> </desc> </func> <func> - <name>minutes(Minutes) -> Milliseconds</name> + <name name="minutes" arity="1"/> <fsummary>Converts <c>Minutes</c>to <c>Milliseconds</c>.</fsummary> <desc> - <p>Return the number of milliseconds in <c>Minutes</c>.</p> + <p>Return the number of milliseconds in <c><anno>Minutes</anno></c>.</p> </desc> </func> <func> - <name>hours(Hours) -> Milliseconds</name> + <name name="hours" arity="1"/> <fsummary>Convert <c>Hours</c>to <c>Milliseconds</c>.</fsummary> <desc> - <p>Returns the number of milliseconds in <c>Hours</c>.</p> + <p>Returns the number of milliseconds in <c><anno>Hours</anno></c>.</p> </desc> </func> <func> - <name>hms(Hours, Minutes, Seconds) -> Milliseconds</name> + <name name="hms" arity="3"/> <fsummary>Convert <c>Hours</c>+<c>Minutes</c>+<c>Seconds</c>to <c>Milliseconds</c>.</fsummary> <desc> - <p>Returns the number of milliseconds in <c>Hours + Minutes + Seconds</c>.</p> + <p>Returns the number of milliseconds in <c><anno>Hours</anno> + <anno>Minutes</anno> + <anno>Seconds</anno></c>.</p> </desc> </func> </funcs> @@ -277,7 +258,6 @@ <section> <title>Examples</title> <p>This example illustrates how to print out "Hello World!" in 5 seconds:</p> - <p></p> <pre> 1> <input>timer:apply_after(5000, io, format, ["~nHello World!~n", []]).</input> {ok,TRef} diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml index e3a25a407b..d02763f75c 100644 --- a/lib/stdlib/doc/src/unicode.xml +++ b/lib/stdlib/doc/src/unicode.xml @@ -38,50 +38,83 @@ <p>It is recommended to only use external encodings for communication with external entities where this is required. When working inside the Erlang/OTP environment, it is recommended to keep binaries in UTF-8 when representing Unicode characters. Latin1 encoding is supported both for backward compatibility and for communication with external entities not supporting Unicode character sets.</p> </description> - <section> - <title>DATA TYPES</title> - <marker id="type-charlist"></marker> - <code type="none"> -unicode_binary() = binary() with characters encoded in UTF-8 coding standard -unicode_char() = integer() representing valid unicode codepoint - -chardata() = charlist() | unicode_binary() - -charlist() = [unicode_char() | unicode_binary() | charlist()] - a unicode_binary is allowed as the tail of the list</code> - - <code type="none"> -external_unicode_binary() = binary() - with characters coded in a user specified Unicode encoding other - than UTF-8 (UTF-16 or UTF-32) - -external_chardata() = external_charlist() | external_unicode_binary() - -external_charlist() = [unicode_char() | external_unicode_binary() | external_charlist()] - an external_unicode_binary is allowed as the tail of the list</code> - - <code type="none"> -latin1_binary() = binary() with characters coded in iso-latin-1 -latin1_char() = integer() representing valid latin1 character (0-255) - -latin1_chardata() = latin1_charlist() | latin1_binary() + <datatypes> + <datatype> + <name name="encoding"/> + </datatype> + <datatype> + <name name="endian"/> + </datatype> + <datatype> + <name name="unicode_binary"/> + <desc> + <p>A binary() with characters encoded in the UTF-8 coding standard.</p> + </desc> + </datatype> + <datatype> + <name name="unicode_char"/> + <desc> + <p>An integer() representing a valid unicode codepoint.</p> + </desc> + </datatype> + <datatype> + <name name="chardata"/> + </datatype> + <datatype> + <name name="charlist"/> + <desc> + <p>A unicode_binary is allowed as the tail of the list.</p> + </desc> + </datatype> + <datatype> + <name name="external_unicode_binary"/> + <desc> + <p>A <c>binary()</c> with characters coded in a user specified Unicode + encoding other than UTF-8 (UTF-16 or UTF-32).</p> + </desc> + </datatype> + <datatype> + <name name="external_chardata"/> + </datatype> + <datatype> + <name name="external_charlist"/> + <desc> + <p>An <c>external_unicode_binary()</c> is allowed as the tail + of the list.</p> + </desc> + </datatype> + <datatype> + <name name="latin1_binary"/> + <desc><p>A <c>binary()</c> with characters coded in iso-latin-1.</p> + </desc> + </datatype> + <datatype> + <name name="latin1_char"/> + <desc><p>An <c>integer()</c> representing valid latin1 + character (0-255).</p> + </desc> + </datatype> + <datatype> + <name name="latin1_chardata"/> + </datatype> + <datatype> + <name name="latin1_charlist"/> + <desc><p>A <c>latin1_binary()</c> is allowed as the tail of + the list.</p> + </desc> + </datatype> + </datatypes> -latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] - a latin1_binary is allowed as the tail of the list</code> - </section> <funcs> <func> - <name>bom_to_encoding(Bin) -> {Encoding,Length}</name> + <name name="bom_to_encoding" arity="1"/> <fsummary>Identify UTF byte order marks in a binary.</fsummary> - <type> - <v>Bin = binary() of byte_size 4 or more</v> - <v>Encoding = latin1 | utf8 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> - <v>Length = int()</v> - </type> + <type name="endian"/> + <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc> <desc> <p>Check for a UTF byte order mark (BOM) in the beginning of a - binary. If the supplied binary <c>Bin</c> begins with a valid + binary. If the supplied binary <c><anno>Bin</anno></c> begins with a valid byte order mark for either UTF-8, UTF-16 or UTF-32, the function returns the encoding identified along with the length of the BOM in bytes.</p> @@ -90,23 +123,24 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] </desc> </func> <func> - <name>characters_to_list(Data) -> list() | {error, list(), RestData} | {incomplete, list(), binary()} </name> + <name name="characters_to_list" arity="1"/> <fsummary>Convert a collection of characters to list of Unicode characters</fsummary> - <type> - <v>Data = latin1_chardata() | chardata() | external_chardata()</v> - <v>RestData = latin1_chardata() | chardata() | external_chardata()</v> - </type> <desc> - <p>Same as characters_to_list(Data,unicode).</p> + <p>Same as characters_to_list(<anno>Data</anno>,unicode).</p> </desc> </func> <func> - <name>characters_to_list(Data, InEncoding) -> list() | {error, list(), RestData} | {incomplete, list(), binary()} </name> + <name>characters_to_list(Data, InEncoding) -> Result</name> <fsummary>Convert a collection of characters to list of Unicode characters</fsummary> <type> - <v>Data = latin1_chardata() | chardata() | external_chardata()</v> - <v>RestData = latin1_chardata() | chardata() | external_chardata()</v> - <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> + <v>Data = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso> + | <seealso marker="#type-chardata">chardata()</seealso> + | <seealso marker="#type-external_chardata">external_chardata()</seealso></v> + <v>Result = list() | {error, list(), RestData} | {incomplete, list(), binary()}</v> + <v>RestData = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso> + | <seealso marker="#type-chardata">chardata()</seealso> + | <seealso marker="#type-external_chardata">external_chardata()</seealso></v> + <v>InEncoding = <seealso marker="#type-encoding">encoding()</seealso></v> </type> <desc> @@ -164,10 +198,16 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] <item>Integers out of range - If <c>InEncoding</c> is <c>latin1</c>, an error occurs whenever an integer greater than 255 is found in the lists. If <c>InEncoding</c> is - of a Unicode type, error occurs whenever an integer greater than - <c>16#10FFFF</c> (the maximum unicode character) or in the - range <c>16#D800</c> to <c>16#DFFF</c> (invalid unicode - range) is found.</item> + of a Unicode type, an error occurs whenever an integer + <list type="bulleted"> + <item>greater than <c>16#10FFFF</c> + (the maximum unicode character),</item> + <item>in the range <c>16#D800</c> to <c>16#DFFF</c> + (invalid unicode range)</item> + <item>or equal to 16#FFFE or 16#FFFF (non characters)</item> + </list> + is found. + </item> <item>UTF encoding incorrect - If <c>InEncoding</c> is one of the UTF types, the bytes in any binaries have to be valid @@ -228,44 +268,42 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] </desc> </func> <func> - <name>characters_to_binary(Data) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name> - <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> <type> - <v>Data = latin1_chardata() | chardata() | external_chardata()</v> - <v>RestData = latin1_chardata() | chardata() | external_chardata()</v> - </type> + <name name="characters_to_binary" arity="1"/> + <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> <desc> <p>Same as characters_to_binary(Data, unicode, unicode).</p> </desc> </func> <func> - <name>characters_to_binary(Data,InEncoding) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name> - <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> <type> - <v>Data = latin1_chardata() | chardata() | external_chardata()</v> - <v>RestData = latin1_chardata() | chardata() | external_chardata()</v> - <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> + <name>characters_to_binary(Data,InEncoding) -> Result</name> + <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> + + <type> + <v>Data = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso> + | <seealso marker="#type-chardata">chardata()</seealso> + | <seealso marker="#type-external_chardata">external_chardata()</seealso></v> + <v>Result = binary() | {error, binary(), RestData} | {incomplete, binary(), binary()}</v> + <v>RestData = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso> + | <seealso marker="#type-chardata">chardata()</seealso> + | <seealso marker="#type-external_chardata">external_chardata()</seealso></v> + <v>InEncoding = <seealso marker="#type-encoding">encoding()</seealso></v> </type> <desc> <p>Same as characters_to_binary(Data, InEncoding, unicode).</p> </desc> </func> <func> - <name>characters_to_binary(Data, InEncoding, OutEncoding) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name> + <name name="characters_to_binary" arity="3"/> <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> - <type> - <v>Data = latin1_chardata() | chardata() | external_chardata()</v> - <v>RestData = latin1_chardata() | chardata() | external_chardata()</v> - <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> - <v>OutEncoding = latin1 | unicode | utf8 | utf16 | utf32| {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> - </type> <desc> <p>This function behaves as <seealso marker="#characters_to_list/2"> characters_to_list/2</seealso>, but produces an binary instead of a unicode list. The - <c>InEncoding</c> defines how input is to be interpreted if + <c><anno>InEncoding</anno></c> defines how input is to be interpreted if binaries are present in the <c>Data</c>, while - <c>OutEncoding</c> defines in what format output is to be + <c><anno>OutEncoding</anno></c> defines in what format output is to be generated.</p> <p>The option <c>unicode</c> is an alias for <c>utf8</c>, as this is the @@ -285,17 +323,13 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] </desc> </func> <func> - <name>encoding_to_bom(InEncoding) -> Bin</name> + <name name="encoding_to_bom" arity="1"/> <fsummary>Create a binary UTF byte order mark from encoding.</fsummary> - <type> - <v>Bin = binary() of byte_size 4 or less</v> - <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v> - <v>Length = int()</v> - </type> + <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc> <desc> <p>Create an UTF byte order mark (BOM) as a binary from the - supplied <c>InEncoding</c>. The BOM is, if supported at all, + supplied <c><anno>InEncoding</anno></c>. The BOM is, if supported at all, expected to be placed first in UTF encoded files or messages.</p> diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index 416df1f02c..0fa7de0a5c 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1999</year> - <year>2010</year> + <year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -52,7 +52,7 @@ <tag>UCS-4</tag> <item>Basically the same as UTF-32, but without some Unicode semantics, defined by IEEE and has little use as a separate encoding standard. For all normal (and possibly abnormal) usages, UTF-32 and UCS-4 are interchangeable.</item> </taglist> -<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a whole in the Unicode range to cope with backward compatibility.</p> +<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a hole in the Unicode range to cope with backward compatibility.</p> <p>Additionally, the codepoint 16#FEFF is used for byte order marks (BOM's) and use of that character is not encouraged in other contexts than that. It actually is valid though, as the character "ZWNBS" (Zero Width Non Breaking Space). BOM's are used to identify encodings and byte order for programs where such parameters are not known in advance. Byte order marks are more seldom used than one could expect, put their use is becoming more widely spread as they provide the means for programs to make educated guesses about the Unicode format of a certain file.</p> </section> <section> diff --git a/lib/stdlib/doc/src/win32reg.xml b/lib/stdlib/doc/src/win32reg.xml index 28960cd098..99fd7fdeb6 100644 --- a/lib/stdlib/doc/src/win32reg.xml +++ b/lib/stdlib/doc/src/win32reg.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2009</year> + <year>2000</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -85,14 +85,22 @@ hkdd HKEY_DYN_DATA</pre> <p>For additional information on the Windows registry consult the Win32 Programmer's Reference.</p> </description> + <datatypes> + <datatype> + <name name="reg_handle"/> + <desc><p>As returned by <seealso marker="#open/1">open/1</seealso>.</p></desc> + </datatype> + <datatype> + <name name="name"/> + </datatype> + <datatype> + <name name="value"/> + </datatype> + </datatypes> <funcs> <func> - <name>change_key(RegHandle, Key) -> ReturnValue</name> + <name name="change_key" arity="2"/> <fsummary>Move to a key in the registry</fsummary> - <type> - <v>RegHandle = term()</v> - <v>Key = string()</v> - </type> <desc> <p>Changes the current key to another key. Works like cd. The key can be specified as a relative path or as an @@ -100,12 +108,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>change_key_create(RegHandle, Key) -> ReturnValue</name> + <name name="change_key_create" arity="2"/> <fsummary>Move to a key, create it if it is not there</fsummary> - <type> - <v>RegHandle = term()</v> - <v>Key = string()</v> - </type> <desc> <p>Creates a key, or just changes to it, if it is already there. Works like a combination of <c>mkdir</c> and <c>cd</c>. Calls the Win32 API function @@ -114,23 +118,16 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>close(RegHandle)-> ReturnValue</name> + <name name="close" arity="1"/> <fsummary>Close the registry.</fsummary> - <type> - <v>RegHandle = term()</v> - </type> <desc> - <p>Closes the registry. After that, the <c>RegHandle</c> cannot + <p>Closes the registry. After that, the <c><anno>RegHandle</anno></c> cannot be used.</p> </desc> </func> <func> - <name>current_key(RegHandle) -> ReturnValue</name> + <name name="current_key" arity="1"/> <fsummary>Return the path to the current key.</fsummary> - <type> - <v>RegHandle = term()</v> - <v>ReturnValue = {ok, string()}</v> - </type> <desc> <p>Returns the path to the current key. This is the equivalent of <c>pwd</c>.</p> <p>Note that the current key is stored in the driver, and might be @@ -138,12 +135,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>delete_key(RegHandle) -> ReturnValue</name> + <name name="delete_key" arity="1"/> <fsummary>Delete the current key</fsummary> - <type> - <v>RegHandle = term()</v> - <v>ReturnValue = ok | {error, ErrorId}</v> - </type> <desc> <p>Deletes the current key, if it is valid. Calls the Win32 API function <c>RegDeleteKey()</c>. Note that this call does not change the current key, @@ -152,12 +145,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>delete_value(RegHandle, Name) -> ReturnValue</name> + <name name="delete_value" arity="2"/> <fsummary>Delete the named value on the current key.</fsummary> - <type> - <v>RegHandle = term()</v> - <v>ReturnValue = ok | {error, ErrorId}</v> - </type> <desc> <p>Deletes a named value on the current key. The atom <c>default</c> is used for the the default value.</p> @@ -165,12 +154,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>expand(String) -> ExpandedString</name> + <name name="expand" arity="1"/> <fsummary>Expand a string with environment variables</fsummary> - <type> - <v>String = string()</v> - <v>ExpandedString = string()</v> - </type> <desc> <p>Expands a string containing environment variables between percent characters. Anything between two % is taken for a environment @@ -180,23 +165,15 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>format_error(ErrorId) -> ErrorString</name> + <name name="format_error" arity="1"/> <fsummary>Convert an POSIX errorcode to a string</fsummary> - <type> - <v>ErrorId = atom()</v> - <v>ErrorString = string()</v> - </type> <desc> <p>Convert an POSIX errorcode to a string (by calling <c>erl_posix_msg:message</c>).</p> </desc> </func> <func> - <name>open(OpenModeList)-> ReturnValue</name> + <name name="open" arity="1"/> <fsummary>Open the registry for reading or writing</fsummary> - <type> - <v>OpenModeList = [OpenMode]</v> - <v>OpenMode = read | write</v> - </type> <desc> <p>Opens the registry for reading or writing. The current key will be the root (<c>HKEY_CLASSES_ROOT</c>). The <c>read</c> flag in the mode list can be omitted.</p> @@ -204,12 +181,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>set_value(RegHandle, Name, Value) -> ReturnValue</name> + <name name="set_value" arity="3"/> <fsummary>Set value at the current registry key with specified name.</fsummary> - <type> - <v>Name = string() | default</v> - <v>Value = string() | integer() | binary()</v> - </type> <desc> <p>Sets the named (or default) value to value. Calls the Win32 API function <c>RegSetValueEx()</c>. The value can be of three types, and @@ -221,13 +194,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>sub_keys(RegHandle) -> ReturnValue</name> + <name name="sub_keys" arity="1"/> <fsummary>Get subkeys to the current key.</fsummary> - <type> - <v>ReturnValue = {ok, SubKeys} | {error, ErrorId}</v> - <v>SubKeys = [SubKey]</v> - <v>SubKey = string()</v> - </type> <desc> <p>Returns a list of subkeys to the current key. Calls the Win32 API function <c>EnumRegKeysEx()</c>.</p> @@ -235,13 +203,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>value(RegHandle, Name) -> ReturnValue</name> + <name name="value" arity="2"/> <fsummary>Get the named value on the current key.</fsummary> - <type> - <v>Name = string() | default</v> - <v>ReturnValue = {ok, Value}</v> - <v>Value = string() | integer() | binary()</v> - </type> <desc> <p>Retrieves the named value (or default) on the current key. Registry values of type <c>REG_SZ</c>, are returned as strings. Type <c>REG_DWORD</c> @@ -249,15 +212,8 @@ hkdd HKEY_DYN_DATA</pre> </desc> </func> <func> - <name>values(RegHandle) -> ReturnValue</name> + <name name="values" arity="1"/> <fsummary>Get all values on the current key.</fsummary> - <type> - <v>ReturnValue = {ok, ValuePairs} | {ok, ErrorId}</v> - <v>ValuePairs = [ValuePair]</v> - <v>ValuePair = {Name, Value}</v> - <v>Name = string | default</v> - <v>Value = string() | integer() | binary()</v> - </type> <desc> <p>Retrieves a list of all values on the current key. The values have types corresponding to the registry types, see <c>value</c>. diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml index 529a70a23d..cf0d581352 100644 --- a/lib/stdlib/doc/src/zip.xml +++ b/lib/stdlib/doc/src/zip.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2006</year><year>2010</year> + <year>2006</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -85,67 +85,55 @@ recreated.</p> </section> - <section> - <title>DATA TYPES</title> - <code type="none"> -zip_file() </code> - <p>The record <c>zip_file</c> contains the following fields.</p> - <taglist> - <tag><c>name = string()</c></tag> - <item> - <p>the name of the file</p> - </item> - <tag><c>info = file_info()</c></tag> - <item> - <p>file info as in - <seealso marker="erts:file#read_file_info/1">file:read_file_info/1</seealso></p> - </item> - <tag><c>comment = string()</c></tag> - <item> - <p>the comment for the file in the zip archive</p> - </item> - <tag><c>offset = integer()</c></tag> - <item> - <p>the offset of the file in the zip archive (used internally)</p> - </item> - <tag><c>comp_size = integer()</c></tag> - <item> - <p>the compressed size of the file (the uncompressed size is found - in <c>info</c>)</p> - </item> - </taglist> - <code type="none">zip_comment</code> - <p>The record <c>zip_comment</c> just contains the archive comment for - a zip archive</p> - <taglist> - <tag><c>comment = string()</c></tag> - <item> - <p>the comment for the zip archive</p> - </item> - </taglist> - </section> + <datatypes> + <datatype> + <name name="zip_comment"/> + <desc> + <p>The record <c>zip_comment</c> just contains the archive comment for + a zip archive</p> + </desc> + </datatype> + <datatype> + <name name="zip_file"/> + <desc> + <p>The record <c>zip_file</c> contains the following fields.</p> + <taglist> + <tag><c>name</c></tag> + <item> + <p>the name of the file</p> + </item> + <tag><c>info</c></tag> + <item> + <p>file info as in + <seealso marker="kernel:file#read_file_info/1">file:read_file_info/1</seealso></p> + </item> + <tag><c>comment</c></tag> + <item> + <p>the comment for the file in the zip archive</p> + </item> + <tag><c>offset</c></tag> + <item> + <p>the offset of the file in the zip archive (used internally)</p> + </item> + <tag><c>comp_size</c></tag> + <item> + <p>the compressed size of the file (the uncompressed size is found + in <c>info</c>)</p> + </item> + </taglist> + </desc> + </datatype> + </datatypes> <funcs> <func> - <name>zip(Name, FileList) -> RetValue</name> - <name>zip(Name, FileList, Options) -> RetValue</name> - <name>create(Name, FileList) -> RetValue</name> - <name>create(Name, FileList, Options) -> RetValue</name> + <name name="zip" arity="2"/> + <name name="zip" arity="3"/> + <name name="create" arity="2"/> + <name name="create" arity="3"/> <fsummary>Create a zip archive with options</fsummary> - <type> - <v>Name = filename()</v> - <v>FileList = [FileSpec]</v> - <v>FileSpec = filename() | {filename(), binary()} | {filename(), binary(), #file_info{}}</v> - <v>Options = [Option]</v> - <v>Option = memory | cooked | verbose | {comment, Comment} | {cwd, CWD} | {compress, What} | {uncompress, What}</v> - <v>What = all | [Extension] | {add, [Extension]} | {del, [Extension]}</v> - <v>Extension = string()</v> - <v>Comment = CWD = string()</v> - <v>RetValue = {ok, Name} | {ok, {Name, binary()}} | {error, Reason}</v> - <v>Reason = term()</v> - </type> <desc> <p>The <marker id="zip_2"></marker><c>zip</c> function creates a - zip archive containing the files specified in <c>FileList</c>.</p> + zip archive containing the files specified in <c><anno>FileList</anno></c>.</p> <p>As synonyms, the functions <c>create/2</c> and <c>create/3</c> are provided, to make it resemble the <c>erl_tar</c> module.</p> <p>The file-list is a list of files, with paths relative to the @@ -161,9 +149,9 @@ zip_file() </code> <c>.Z</c>, <c>.zip</c>, <c>.zoo</c>, <c>.arc</c>, <c>.lzh</c>, <c>.arj</c>.</p> <p>It is possible to override the default behavior and - explicitly control what types of files should be - compressed by using the <c>{compress, What}</c> and - <c>{uncompress, What}</c> options. It is possible to have + explicitly control what types of files that should be + compressed by using the <c>{compress, <anno>What</anno>}</c> and + <c>{uncompress, <anno>What</anno>}</c> options. It is possible to have several <c>compress</c> and <c>uncompress</c> options. In order to trigger compression of a file, its extension must match with the @@ -191,22 +179,22 @@ zip_file() </code> <tag><c>memory</c></tag> <item> <p>The output will not be to a file, but instead as a tuple - <c>{FileName, binary()}</c>. The binary will be a full zip + <c>{<anno>FileName</anno>, binary()}</c>. The binary will be a full zip archive with header, and can be extracted with for instance <c>unzip/2</c>.</p> </item> - <tag><c>{comment, Comment}</c></tag> + <tag><c>{comment, <anno>Comment</anno>}</c></tag> <item> <p>Add a comment to the zip-archive.</p> </item> - <tag><c>{cwd, CWD}</c></tag> + <tag><c>{cwd, <anno>CWD</anno>}</c></tag> <item> <p>Use the given directory as current directory, it will be prepended to file names when adding them, although it will not be in the zip-archive. (Acting like a file:set_cwd/1, but without changing the global cwd property.)</p> </item> - <tag><c>{compress, What}</c></tag> + <tag><c>{compress, <anno>What</anno>}</c></tag> <item> <p>Controls what types of files will be compressed. It is by default set to <c>all</c>. The @@ -215,18 +203,18 @@ zip_file() </code> <tag><c>all</c></tag> <item><p> means that all files will be compressed (as long as they pass the <c>uncompress</c> condition).</p></item> - <tag><c>[Extension]</c></tag> + <tag><c>[<anno>Extension</anno>]</c></tag> <item><p>means that only files with exactly these extensions will be compressed.</p></item> - <tag><c>{add,[Extension]}</c></tag> + <tag><c>{add,[<anno>Extension</anno>]}</c></tag> <item><p>adds these extensions to the list of compress extensions.</p></item> - <tag><c>{del,[Extension]}</c></tag> + <tag><c>{del,[<anno>Extension</anno>]}</c></tag> <item><p>deletes these extensions from the list of compress extensions.</p></item> </taglist> </item> - <tag><c>{uncompress, What}</c></tag> + <tag><c>{uncompress, <anno>What</anno>}</c></tag> <item> <p>Controls what types of files will be uncompressed. It is by default set to <c>[".Z",".zip",".zoo",".arc",".lzh",".arj"]</c>. @@ -234,13 +222,13 @@ zip_file() </code> <taglist> <tag><c>all</c></tag> <item><p> means that no files will be compressed.</p></item> - <tag><c>[Extension]</c></tag> + <tag><c>[<anno>Extension</anno>]</c></tag> <item><p>means that files with these extensions will be uncompressed.</p></item> - <tag><c>{add,[Extension]}</c></tag> + <tag><c>{add,[<anno>Extension</anno>]}</c></tag> <item><p>adds these extensions to the list of uncompress extensions.</p></item> - <tag><c>{del,[Extension]}</c></tag> + <tag><c>{del,[<anno>Extension</anno>]}</c></tag> <item><p>deletes these extensions from the list of uncompress extensions.</p></item> </taglist> @@ -249,41 +237,27 @@ zip_file() </code> </desc> </func> <func> - <name>unzip(Archive) -> RetValue</name> - <name>unzip(Archive, Options) -> RetValue</name> - <name>extract(Archive) -> RetValue</name> - <name>extract(Archive, Options) -> RetValue</name> + <name name="unzip" arity="1"/> + <name name="unzip" arity="2"/> + <name name="extract" arity="1"/> + <name name="extract" arity="2"/> <fsummary>Extract files from a zip archive</fsummary> - <type> - <v>Archive = filename() | binary()</v> - <v>Options = [Option]</v> - <v>Option = {file_list, FileList} | keep_old_files | verbose | memory | {file_filter, FileFilter} | {cwd, CWD}</v> - <v>FileList = [filename()]</v> - <v>FileBinList = [{filename(),binary()}]</v> - <v>FileFilter = fun(ZipFile) -> true | false</v> - <v>CWD = string()</v> - <v>ZipFile = zip_file()</v> - <v>RetValue = {ok,FileList} | {ok,FileBinList} | {error, Reason} | {error, {Name, Reason}}</v> - <v>Reason = term()</v> - </type> <desc> - <p>The <marker id="unzip_1"></marker> -<c>unzip/1</c> function extracts - all files from a zip archive. The - <marker id="unzip_2"></marker> -<c>unzip/2</c> function provides options - to extract some files, and more.</p> - <p>If the <c>Archive</c> argument is given as a binary, + <p>The <marker id="unzip_1"></marker><c>unzip/1</c> function extracts + all files from a zip archive. + The <marker id="unzip_2"></marker><c>unzip/2</c> function provides + options to extract some files, and more.</p> + <p>If the <c><anno>Archive</anno></c> argument is given as a binary, the contents of the binary is assumed to be a zip archive, otherwise it should be a filename.</p> <p>The following options are available:</p> <taglist> - <tag><c>{file_list, FileList}</c></tag> + <tag><c>{file_list, <anno>FileList</anno>}</c></tag> <item> <p>By default, all files will be extracted from the zip - archive. With the <c>{file_list,FileList}</c> option, + archive. With the <c>{file_list, <anno>FileList</anno>}</c> option, the <c>unzip/2</c> function will only extract the files - whose names are included in <c>FileList</c>. The full + whose names are included in <c><anno>FileList</anno></c>. The full paths, including the names of all sub directories within the zip archive, must be specified.</p> </item> @@ -329,29 +303,29 @@ zip_file() </code> </desc> </func> <func> - <name>foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason}</name> + <name name="foldl" arity="3"/> <fsummary>Fold a function over all files in a zip archive</fsummary> - <type> - <v>Fun = fun(FileInArchive, GetInfo, GetBin, AccIn) -> AccOut</v> - <v>FileInArchive = filename()</v> - <v>GetInfo = fun() -> #file_info{}</v> - <v>GetBin = fun() -> binary()</v> - <v>Acc0 = Acc1 = AccIn = AccOut = term()</v> - <v>Archive = filename() | {filename(), binary()}</v> - </type> <desc> <p>The <marker id="foldl_3"></marker> <c>foldl/3</c> function - calls <c>Fun(FileInArchive, GetInfo, GetBin, AccIn)</c> on - successive files in the <c>Archive</c>, starting with <c>AccIn - == Acc0</c>. <c>FileInArchive</c> is the name that the file - has in the archive. <c>GetInfo</c> is a fun that returns info - about the the file. <c>GetBin</c> returns the contents of the - file. Both <c>GetInfo</c> and <c>GetBin</c> must be called - within the <c>Fun</c>. Their behavior is undefined if they are - called outside the context of the <c>Fun</c>. The <c>Fun</c> + calls <c><anno>Fun</anno>(<anno>FileInArchive</anno>, <anno>GetInfo + </anno>, <anno>GetBin</anno>, <anno>AccIn</anno>)</c> on + successive files in the <c>Archive</c>, starting with + <c><anno>AccIn</anno> + == <anno>Acc0</anno></c>. <c><anno>FileInArchive</anno></c> is + the name that the file + has in the archive. <c><anno>GetInfo</anno></c> is a fun that + returns info + about the the file. <c><anno>GetBin</anno></c> returns the contents + of the + file. Both <c><anno>GetInfo</anno></c> and <c><anno>GetBin</anno></c> + must be called + within the <c><anno>Fun</anno></c>. Their behavior is undefined if + they are + called outside the context of the <c><anno>Fun</anno></c>. + The <c><anno>Fun</anno></c> must return a new accumulator which is passed to the next call. <c>foldl/3</c> returns the final value of the - accumulator. <c>Acc0</c> is returned if the archive is + accumulator. <c><anno>Acc0</anno></c> is returned if the archive is empty. It is not necessary to iterate over all files in the archive. The iteration may be ended prematurely in a controlled manner by throwing an exception.</p> @@ -387,26 +361,16 @@ zip_file() </code> </desc> </func> <func> - <name>list_dir(Archive) -> RetValue</name> - <name>list_dir(Archive, Options)</name> - <name>table(Archive) -> RetValue</name> - <name>table(Archive, Options)</name> + <name name="list_dir" arity="1"/> + <name name="list_dir" arity="2"/> + <name name="table" arity="1" /> + <name name="table" arity="2"/> <fsummary>Retrieve the name of all files in a zip archive</fsummary> - <type> - <v>Archive = filename() | binary()</v> - <v>RetValue = {ok, [Comment, Files]} | {error, Reason}</v> - <v>Comment = zip_comment()</v> - <v>Files = [zip_file()]</v> - <v>Options = [Option]</v> - <v>Option = cooked</v> - <v>Reason = term()</v> - </type> <desc> - <p>The <marker id="list_dir_1"></marker> -<c>list_dir/1</c> function retrieves - the names of all files in the zip archive <c>Archive</c>. The - <marker id="list_dir_2"></marker> -<c>list_dir/2</c> function provides options.</p> + <p>The <marker id="list_dir_1"></marker><c>list_dir/1</c> + function retrieves the names of all files in the zip archive + <c><anno>Archive</anno></c>. The <marker id="list_dir_2"></marker> + <c>list_dir/2</c> function provides options.</p> <p>As synonyms, the functions <c>table/2</c> and <c>table/3</c> are provided, to make it resemble the <c>erl_tar</c> module.</p> <p>The result value is the tuple <c>{ok, List}</c>, where <c>List</c> @@ -425,46 +389,30 @@ zip_file() </code> </desc> </func> <func> - <name>t(Archive)</name> + <name name="t" arity="1"/> <fsummary>Print the name of each file in a zip archive</fsummary> - <type> - <v>Archive = filename() | binary() | ZipHandle</v> - <v>ZipHandle = pid()</v> - </type> <desc> - <p>The <marker id="t_1"></marker> -<c>t/1</c> function prints the names - of all files in the zip archive <c>Archive</c> to the Erlang shell. + <p>The <marker id="t_1"></marker><c>t/1</c> function prints the names + of all files in the zip archive <c><anno>Archive</anno></c> to the Erlang shell. (Similar to "<c>tar t</c>".)</p> </desc> </func> <func> - <name>tt(Archive)</name> + <name name="tt" arity="1"/> <fsummary>Print name and information for each file in a zip archive</fsummary> - <type> - <v>Archive = filename() | binary()</v> - </type> <desc> - <p>The <marker id="tt_1"></marker> -<c>tt/1</c> function prints names and - information about all files in the zip archive <c>Archive</c> to + <p>The <marker id="tt_1"></marker><c>tt/1</c> function prints names and + information about all files in the zip archive <c><anno>Archive</anno></c> to the Erlang shell. (Similar to "<c>tar tv</c>".)</p> </desc> </func> <func> - <name>zip_open(Archive) -> {ok, ZipHandle} | {error, Reason}</name> - <name>zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason}</name> + <name name="zip_open" arity="1"/> + <name name="zip_open" arity="2"/> <fsummary>Open an archive and return a handle to it</fsummary> - <type> - <v>Archive = filename() | binary()</v> - <v>Options = [Option]</v> - <v>Options = cooked | memory | {cwd, CWD}</v> - <v>CWD = string()</v> - <v>ZipHandle = pid()</v> - </type> <desc> - <p>The <marker id="zip_open"></marker> -<c>zip_open</c> function opens a + <p>The <marker id="zip_open"></marker><c>zip_open</c> function + opens a zip archive, and reads and saves its directory. This means that subsequently reading files from the archive will be faster than unzipping files one at a time with <c>unzip</c>.</p> @@ -472,32 +420,21 @@ zip_file() </code> </desc> </func> <func> - <name>zip_list_dir(ZipHandle) -> Result | {error, Reason}</name> + <name name="zip_list_dir" arity="1"/> <fsummary>Return a table of files in open zip archive</fsummary> - <type> - <v>Result = [ZipComment, ZipFile...]</v> - <v>ZipComment = #zip_comment{}</v> - <v>ZipFile = #zip_file{}</v> - <v>ZipHandle = pid()</v> - </type> <desc> - <p>The <marker id="zip_list_dir"></marker> -<c>zip_list_dir/1</c> function - returns the file list of an open zip archive.</p> + <p>The <marker id="zip_list_dir"></marker> + <c>zip_list_dir/1</c> function + returns the file list of an open zip archive. The first returned + element is the zip archive comment.</p> </desc> </func> <func> - <name>zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason}</name> - <name>zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason}</name> + <name name="zip_get" arity="1"/> + <name name="zip_get" arity="2"/> <fsummary>Extract files from an open archive</fsummary> - <type> - <v>FileName = filename()</v> - <v>ZipHandle = pid()</v> - <v>Result = filename() | {filename(), binary()}</v> - </type> <desc> - <p>The <marker id="zip_get"></marker> -<c>zip_get</c> function extracts + <p>The <marker id="zip_get"></marker><c>zip_get</c> function extracts one or all files from an open archive.</p> <p>The files will be unzipped to memory or to file, depending on the options given to the <c>zip_open</c> function when the @@ -505,15 +442,11 @@ zip_file() </code> </desc> </func> <func> - <name>zip_close(ZipHandle) -> ok | {error, einval}</name> + <name name="zip_close" arity="1"/> <fsummary>Close an open archive</fsummary> - <type> - <v>ZipHandle = pid()</v> - </type> <desc> - <p>The <marker id="zip_close"></marker> -<c>zip_close/1</c> function closes - a zip archive, previously opened with <c>zip_open</c>. All + <p>The <marker id="zip_close"></marker><c>zip_close/1</c> function + closes a zip archive, previously opened with <c>zip_open</c>. All resources are closed, and the handle should not be used after closing.</p> </desc> diff --git a/lib/stdlib/include/zip.hrl b/lib/stdlib/include/zip.hrl index 2b5ddc1dfe..6e3ed9c78a 100644 --- a/lib/stdlib/include/zip.hrl +++ b/lib/stdlib/include/zip.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ -record(zip_file, { name :: string(), % file name - info :: #file_info{}, + info :: file:file_info(), comment :: string(), % zip file comment offset :: non_neg_integer(), % offset of file's local header in archive comp_size :: non_neg_integer() % compressed size diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 83576c9fd3..2f69e2b0a4 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -163,17 +163,17 @@ -type array_indx() :: non_neg_integer(). --type array_opt() :: 'fixed' | non_neg_integer() - | {'default', term()} | {'fixed', boolean()} - | {'size', non_neg_integer()}. +-type array_opt() :: {'fixed', boolean()} | 'fixed' + | {'default', Value :: term()} + | {'size', N :: non_neg_integer()} + | (N :: non_neg_integer()). -type array_opts() :: array_opt() | [array_opt()]. --type indx_pair() :: {array_indx(), term()}. +-type indx_pair() :: {Index :: array_indx(), Value :: term()}. -type indx_pairs() :: [indx_pair()]. %%-------------------------------------------------------------------------- -%% @spec () -> array() %% @doc Create a new, extendible array with initial size zero. %% @equiv new([]) %% @@ -185,7 +185,6 @@ new() -> new([]). -%% @spec (Options::term()) -> array() %% @doc Create a new array according to the given options. By default, %% the array is extendible and has initial size zero. Array indices %% start at 0. @@ -224,12 +223,11 @@ new() -> %% @see from_list/2 %% @see fix/1 --spec new(array_opts()) -> array(). +-spec new(Options :: array_opts()) -> array(). new(Options) -> new_0(Options, 0, false). -%% @spec (Size::integer(), Options::term()) -> array() %% @doc Create a new array according to the given size and options. If %% `Size' is not a nonnegative integer, the call fails with reason %% `badarg'. By default, the array has fixed size. Note that any size @@ -245,7 +243,7 @@ new(Options) -> %% %% @see new/1 --spec new(non_neg_integer(), array_opts()) -> array(). +-spec new(Size :: non_neg_integer(), Options :: array_opts()) -> array(). new(Size, Options) when is_integer(Size), Size >= 0 -> new_0(Options, Size, true); @@ -293,13 +291,12 @@ find_max(_I, M) -> M. -%% @spec (X::term()) -> boolean() %% @doc Returns `true' if `X' appears to be an array, otherwise `false'. %% Note that the check is only shallow; there is no guarantee that `X' %% is a well-formed array representation even if this function returns %% `true'. --spec is_array(term()) -> boolean(). +-spec is_array(X :: term()) -> boolean(). is_array(#array{size = Size, max = Max}) when is_integer(Size), is_integer(Max) -> @@ -308,25 +305,23 @@ is_array(_) -> false. -%% @spec (array()) -> integer() %% @doc Get the number of entries in the array. Entries are numbered %% from 0 to `size(Array)-1'; hence, this is also the index of the first %% entry that is guaranteed to not have been previously set. %% @see set/3 %% @see sparse_size/1 --spec size(array()) -> non_neg_integer(). +-spec size(Array :: array()) -> non_neg_integer(). size(#array{size = N}) -> N; size(_) -> erlang:error(badarg). -%% @spec (array()) -> term() %% @doc Get the value used for uninitialized entries. %% %% @see new/2 --spec default(array()) -> term(). +-spec default(Array :: array()) -> term(). default(#array{default = D}) -> D; default(_) -> erlang:error(badarg). @@ -405,23 +400,21 @@ new_test_() -> -endif. -%% @spec (array()) -> array() %% @doc Fix the size of the array. This prevents it from growing %% automatically upon insertion; see also {@link set/3}. %% @see relax/1 --spec fix(array()) -> array(). +-spec fix(Array :: array()) -> array(). fix(#array{}=A) -> A#array{max = 0}. -%% @spec (array()) -> boolean() %% @doc Check if the array has fixed size. %% Returns `true' if the array is fixed, otherwise `false'. %% @see fix/1 --spec is_fix(array()) -> boolean(). +-spec is_fix(Array :: array()) -> boolean(). is_fix(#array{max = 0}) -> true; is_fix(#array{}) -> false. @@ -455,12 +448,11 @@ fix_test_() -> -endif. -%% @spec (array()) -> array() %% @doc Make the array resizable. (Reverses the effects of {@link %% fix/1}.) %% @see fix/1 --spec relax(array()) -> array(). +-spec relax(Array :: array()) -> array(). relax(#array{size = N}=A) -> A#array{max = find_max(N-1, ?LEAFSIZE)}. @@ -481,12 +473,11 @@ relax_test_() -> -endif. -%% @spec (integer(), array()) -> array() %% @doc Change the size of the array. If `Size' is not a nonnegative %% integer, the call fails with reason `badarg'. If the given array has %% fixed size, the resulting array will also have fixed size. --spec resize(non_neg_integer(), array()) -> array(). +-spec resize(Size :: non_neg_integer(), Array :: array()) -> array(). resize(Size, #array{size = N, max = M, elements = E}=A) when is_integer(Size), Size >= 0 -> @@ -510,8 +501,6 @@ resize(_Size, _) -> erlang:error(badarg). -%% @spec (array()) -> array() - %% @doc Change the size of the array to that reported by {@link %% sparse_size/1}. If the given array has fixed size, the resulting %% array will also have fixed size. @@ -519,7 +508,7 @@ resize(_Size, _) -> %% @see resize/2 %% @see sparse_size/1 --spec resize(array()) -> array(). +-spec resize(Array :: array()) -> array(). resize(Array) -> resize(sparse_size(Array), Array). @@ -559,7 +548,6 @@ resize_test_() -> -endif. -%% @spec (integer(), term(), array()) -> array() %% @doc Set entry `I' of the array to `Value'. If `I' is not a %% nonnegative integer, or if the array has fixed size and `I' is larger %% than the maximum index, the call fails with reason `badarg'. @@ -570,7 +558,7 @@ resize_test_() -> %% @see get/2 %% @see reset/2 --spec set(array_indx(), term(), array()) -> array(). +-spec set(I :: array_indx(), Value :: term(), Array :: array()) -> array(). set(I, Value, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -624,7 +612,6 @@ expand(I, _S, X, D) -> setelement(I+1, ?NEW_LEAF(D), X). -%% @spec (integer(), array()) -> term() %% @doc Get the value of entry `I'. If `I' is not a nonnegative %% integer, or if the array has fixed size and `I' is larger than the %% maximum index, the call fails with reason `badarg'. @@ -634,7 +621,7 @@ expand(I, _S, X, D) -> %% @see set/3 --spec get(array_indx(), array()) -> term(). +-spec get(I :: array_indx(), Array :: array()) -> term(). get(I, #array{size = N, max = M, elements = E, default = D}) when is_integer(I), I >= 0 -> @@ -660,7 +647,6 @@ get_1(I, E, _D) -> element(I+1, E). -%% @spec (integer(), array()) -> array() %% @doc Reset entry `I' to the default value for the array. %% If the value of entry `I' is the default value the array will be %% returned unchanged. Reset will never change size of the array. @@ -675,7 +661,7 @@ get_1(I, E, _D) -> %% TODO: a reset_range function --spec reset(array_indx(), array()) -> array(). +-spec reset(I :: array_indx(), Array :: array()) -> array(). reset(I, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -756,13 +742,12 @@ set_get_test_() -> -endif. -%% @spec (array()) -> list() %% @doc Converts the array to a list. %% %% @see from_list/2 %% @see sparse_to_list/1 --spec to_list(array()) -> list(). +-spec to_list(Array :: array()) -> list(). to_list(#array{size = 0}) -> []; @@ -831,12 +816,11 @@ to_list_test_() -> -endif. -%% @spec (array()) -> list() %% @doc Converts the array to a list, skipping default-valued entries. %% %% @see to_list/1 --spec sparse_to_list(array()) -> list(). +-spec sparse_to_list(Array :: array()) -> list(). sparse_to_list(#array{size = 0}) -> []; @@ -901,15 +885,13 @@ sparse_to_list_test_() -> -endif. -%% @spec (list()) -> array() %% @equiv from_list(List, undefined) --spec from_list(list()) -> array(). +-spec from_list(List :: list()) -> array(). from_list(List) -> from_list(List, undefined). -%% @spec (list(), term()) -> array() %% @doc Convert a list to an extendible array. `Default' is used as the value %% for uninitialized entries of the array. If `List' is not a proper list, %% the call fails with reason `badarg'. @@ -917,7 +899,7 @@ from_list(List) -> %% @see new/2 %% @see to_list/1 --spec from_list(list(), term()) -> array(). +-spec from_list(List :: list(), Default :: term()) -> array(). from_list([], Default) -> new({default,Default}); @@ -1011,13 +993,12 @@ from_list_test_() -> -endif. -%% @spec (array()) -> [{Index::integer(), Value::term()}] %% @doc Convert the array to an ordered list of pairs `{Index, Value}'. %% %% @see from_orddict/2 %% @see sparse_to_orddict/1 --spec to_orddict(array()) -> indx_pairs(). +-spec to_orddict(Array :: array()) -> indx_pairs(). to_orddict(#array{size = 0}) -> []; @@ -1104,13 +1085,12 @@ to_orddict_test_() -> -endif. -%% @spec (array()) -> [{Index::integer(), Value::term()}] %% @doc Convert the array to an ordered list of pairs `{Index, Value}', %% skipping default-valued entries. %% %% @see to_orddict/1 --spec sparse_to_orddict(array()) -> indx_pairs(). +-spec sparse_to_orddict(Array :: array()) -> indx_pairs(). sparse_to_orddict(#array{size = 0}) -> []; @@ -1188,15 +1168,13 @@ sparse_to_orddict_test_() -> -endif. -%% @spec (list()) -> array() %% @equiv from_orddict(Orddict, undefined) --spec from_orddict(indx_pairs()) -> array(). +-spec from_orddict(Orddict :: indx_pairs()) -> array(). from_orddict(Orddict) -> from_orddict(Orddict, undefined). -%% @spec (list(), term()) -> array() %% @doc Convert an ordered list of pairs `{Index, Value}' to a %% corresponding extendible array. `Default' is used as the value for %% uninitialized entries of the array. If `List' is not a proper, @@ -1206,7 +1184,7 @@ from_orddict(Orddict) -> %% @see new/2 %% @see to_orddict/1 --spec from_orddict(indx_pairs(), term()) -> array(). +-spec from_orddict(Orddict :: indx_pairs(), Default :: term()) -> array(). from_orddict([], Default) -> new({default,Default}); @@ -1392,7 +1370,6 @@ from_orddict_test_() -> -endif. -%% @spec (Function, array()) -> array() %% Function = (Index::integer(), Value::term()) -> term() %% @doc Map the given function onto each element of the array. The %% elements are visited in order from the lowest index to the highest. @@ -1402,7 +1379,8 @@ from_orddict_test_() -> %% @see foldr/3 %% @see sparse_map/2 --spec map(fun((array_indx(), _) -> _), array()) -> array(). +-spec map(Function, Array :: array()) -> array() when + Function :: fun((Index :: array_indx(), Value :: _) -> _). map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1485,7 +1463,6 @@ map_test_() -> -endif. -%% @spec (Function, array()) -> array() %% Function = (Index::integer(), Value::term()) -> term() %% @doc Map the given function onto each element of the array, skipping %% default-valued entries. The elements are visited in order from the @@ -1494,7 +1471,8 @@ map_test_() -> %% %% @see map/2 --spec sparse_map(fun((array_indx(), _) -> _), array()) -> array(). +-spec sparse_map(Function, Array :: array()) -> array() when + Function :: fun((Index :: array_indx(), Value :: _) -> _). sparse_map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1580,9 +1558,6 @@ sparse_map_test_() -> -endif. -%% @spec (Function, InitialAcc::term(), array()) -> term() -%% Function = (Index::integer(), Value::term(), Acc::term()) -> -%% term() %% @doc Fold the elements of the array using the given function and %% initial accumulator value. The elements are visited in order from the %% lowest index to the highest. If `Function' is not a function, the @@ -1592,7 +1567,8 @@ sparse_map_test_() -> %% @see map/2 %% @see sparse_foldl/3 --spec foldl(fun((array_indx(), _, A) -> B), A, array()) -> B. +-spec foldl(Function, InitialAcc :: A, Array :: array()) -> B when + Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1656,9 +1632,6 @@ foldl_test_() -> -endif. -%% @spec (Function, InitialAcc::term(), array()) -> term() -%% Function = (Index::integer(), Value::term(), Acc::term()) -> -%% term() %% @doc Fold the elements of the array using the given function and %% initial accumulator value, skipping default-valued entries. The %% elements are visited in order from the lowest index to the highest. @@ -1667,7 +1640,8 @@ foldl_test_() -> %% @see foldl/3 %% @see sparse_foldr/3 --spec sparse_foldl(fun((array_indx(), _, A) -> B), A, array()) -> B. +-spec sparse_foldl(Function, InitialAcc :: A, Array :: array()) -> B when + Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). sparse_foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1735,9 +1709,6 @@ sparse_foldl_test_() -> -endif. -%% @spec (Function, InitialAcc::term(), array()) -> term() -%% Function = (Index::integer(), Value::term(), Acc::term()) -> -%% term() %% @doc Fold the elements of the array right-to-left using the given %% function and initial accumulator value. The elements are visited in %% order from the highest index to the lowest. If `Function' is not a @@ -1746,7 +1717,8 @@ sparse_foldl_test_() -> %% @see foldl/3 %% @see map/2 --spec foldr(fun((array_indx(), _, A) -> B), A, array()) -> B. +-spec foldr(Function, InitialAcc :: A, Array :: array()) -> B when + Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1815,9 +1787,6 @@ foldr_test_() -> -endif. -%% @spec (Function, InitialAcc::term(), array()) -> term() -%% Function = (Index::integer(), Value::term(), Acc::term()) -> -%% term() %% @doc Fold the elements of the array right-to-left using the given %% function and initial accumulator value, skipping default-valued %% entries. The elements are visited in order from the highest index to @@ -1827,7 +1796,8 @@ foldr_test_() -> %% @see foldr/3 %% @see sparse_foldl/3 --spec sparse_foldr(fun((array_indx(), _, A) -> B), A, array()) -> B. +-spec sparse_foldr(Function, InitialAcc :: A, Array :: array()) -> B when + Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). sparse_foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1870,7 +1840,6 @@ sparse_foldr_3(I, T, Ix, A, F, D) -> end. -%% @spec (array()) -> integer() %% @doc Get the number of entries in the array up until the last %% non-default valued entry. In other words, returns `I+1' if `I' is the %% last non-default valued entry in the array, or zero if no such entry @@ -1878,7 +1847,7 @@ sparse_foldr_3(I, T, Ix, A, F, D) -> %% @see size/1 %% @see resize/1 --spec sparse_size(array()) -> non_neg_integer(). +-spec sparse_size(Array :: array()) -> non_neg_integer(). sparse_size(A) -> F = fun (I, _V, _A) -> throw({value, I}) end, diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl index a14a72ac6d..5d800e87b8 100644 --- a/lib/stdlib/src/base64.erl +++ b/lib/stdlib/src/base64.erl @@ -38,7 +38,9 @@ %% Description: Encodes a plain ASCII string (or binary) into base64. %%------------------------------------------------------------------------- --spec encode_to_string(string() | binary()) -> ascii_string(). +-spec encode_to_string(Data) -> Base64String when + Data :: string() | binary(), + Base64String :: ascii_string(). encode_to_string(Bin) when is_binary(Bin) -> encode_to_string(binary_to_list(Bin)); @@ -53,7 +55,9 @@ encode_to_string(List) when is_list(List) -> %% Description: Encodes a plain ASCII string (or binary) into base64. %%------------------------------------------------------------------------- --spec encode(string() | binary()) -> binary(). +-spec encode(Data) -> Base64 when + Data :: string() | binary(), + Base64 :: binary(). encode(Bin) when is_binary(Bin) -> encode_binary(Bin); @@ -102,14 +106,18 @@ encode_binary(Bin) -> %% whereas decode crashes if an illegal character is found %%------------------------------------------------------------------------- --spec decode(string() | binary()) -> binary(). +-spec decode(Base64) -> Data when + Base64 :: string() | binary(), + Data :: binary(). decode(Bin) when is_binary(Bin) -> decode_binary(<<>>, Bin); decode(List) when is_list(List) -> list_to_binary(decode_l(List)). --spec mime_decode(string() | binary()) -> binary(). +-spec mime_decode(Base64) -> Data when + Base64 :: string() | binary(), + Data :: binary(). mime_decode(Bin) when is_binary(Bin) -> mime_decode_binary(<<>>, Bin); @@ -139,14 +147,18 @@ mime_decode_l(List) -> %% whereas decode crashes if an illegal character is found %%------------------------------------------------------------------------- --spec decode_to_string(string() | binary()) -> string(). +-spec decode_to_string(Base64) -> DataString when + Base64 :: string() | binary(), + DataString :: string(). decode_to_string(Bin) when is_binary(Bin) -> decode_to_string(binary_to_list(Bin)); decode_to_string(List) when is_list(List) -> decode_l(List). --spec mime_decode_to_string(string() | binary()) -> string(). +-spec mime_decode_to_string(Base64) -> DataString when + Base64 :: string() | binary(), + DataString :: string(). mime_decode_to_string(Bin) when is_binary(Bin) -> mime_decode_to_string(binary_to_list(Bin)); diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index 74d4ad3da7..e9a5e6831e 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,13 +54,9 @@ -type beam() :: module() | file:filename() | binary(). -%% XXX: THE FOLLOWING SHOULD BE IMPORTED FROM SOMEWHERE ELSE --type forms() :: term(). +-type forms() :: [erl_parse:abstract_form()]. --type abst_vsn() :: atom(). --type abst_code() :: {abst_vsn(), forms()} | 'no_abstract_code'. --type attribute() :: atom(). --type attrvalue() :: term(). +-type abst_code() :: {AbstVersion :: atom(), forms()} | 'no_abstract_code'. -type dataB() :: binary(). -type index() :: non_neg_integer(). -type label() :: integer(). @@ -74,9 +70,9 @@ | 'atoms'. -type chunkref() :: chunkname() | chunkid(). --type attrib_entry() :: {attribute(), [attrvalue()]}. --type compinfo_entry() :: {atom(), term()}. --type labeled_entry() :: {atom(), arity(), label()}. +-type attrib_entry() :: {Attribute :: atom(), [AttributeValue :: term()]}. +-type compinfo_entry() :: {InfoKey :: atom(), term()}. +-type labeled_entry() :: {Function :: atom(), arity(), label()}. -type chunkdata() :: {chunkid(), dataB()} | {'abstract_code', abst_code()} @@ -85,20 +81,17 @@ | {'exports', [{atom(), arity()}]} | {'labeled_exports', [labeled_entry()]} | {'imports', [mfa()]} - | {'indexed_imports', [{index(), module(), atom(), arity()}]} + | {'indexed_imports', [{index(), module(), Function :: atom(), arity()}]} | {'locals', [{atom(), arity()}]} | {'labeled_locals', [labeled_entry()]} | {'atoms', [{integer(), atom()}]}. --type info_pair() :: {'file', file:filename()} - | {'binary', binary()} - | {'module', module()} - | {'chunks', [{chunkid(), integer(), integer()}]}. - %% Error reasons -type info_rsn() :: {'chunk_too_big', file:filename(), - chunkid(), integer(), integer()} - | {'invalid_beam_file', file:filename(), integer()} + chunkid(), ChunkSize :: non_neg_integer(), + FileSize :: non_neg_integer()} + | {'invalid_beam_file', file:filename(), + Position :: non_neg_integer()} | {'invalid_chunk', file:filename(), chunkid()} | {'missing_chunk', file:filename(), chunkid()} | {'not_a_beam_file', file:filename()} @@ -118,20 +111,34 @@ %% Exported functions %% --spec info(beam()) -> [info_pair()] | {'error', 'beam_lib', info_rsn()}. +-spec info(Beam) -> [InfoPair] | {'error', 'beam_lib', info_rsn()} when + Beam :: beam(), + InfoPair :: {'file', Filename :: file:filename()} + | {'binary', Binary :: binary()} + | {'module', Module :: module()} + | {'chunks', [{ChunkId :: chunkid(), + Pos :: non_neg_integer(), + Size :: non_neg_integer()}]}. info(File) -> read_info(beam_filename(File)). --spec chunks(beam(), [chunkref()]) -> - {'ok', {module(), [chunkdata()]}} | {'error', 'beam_lib', chnk_rsn()}. +-spec chunks(Beam, ChunkRefs) -> + {'ok', {module(), [chunkdata()]}} | + {'error', 'beam_lib', chnk_rsn()} when + Beam :: beam(), + ChunkRefs :: [chunkref()]. chunks(File, Chunks) -> read_chunk_data(File, Chunks). --spec chunks(beam(), [chunkref()], ['allow_missing_chunks']) -> - {'ok', {module(), [{chunkref(), chunkdata() | 'missing_chunk'}]}} - | {'error', 'beam_lib', chnk_rsn()}. +-spec chunks(Beam, ChunkRefs, Options) -> + {'ok', {module(), [ChunkResult]}} | + {'error', 'beam_lib', chnk_rsn()} when + Beam :: beam(), + ChunkRefs :: [chunkref()], + Options :: ['allow_missing_chunks'], + ChunkResult :: chunkdata() | {ChunkRef :: chunkref(), 'missing_chunk'}. chunks(File, Chunks, Options) -> try read_chunk_data(File, Chunks, Options) @@ -142,49 +149,65 @@ chunks(File, Chunks, Options) -> all_chunks(File) -> read_all_chunks(File). --spec cmp(beam(), beam()) -> 'ok' | {'error', 'beam_lib', cmp_rsn()}. +-spec cmp(Beam1, Beam2) -> 'ok' | {'error', 'beam_lib', cmp_rsn()} when + Beam1 :: beam(), + Beam2 :: beam(). cmp(File1, File2) -> try cmp_files(File1, File2) catch Error -> Error end. --spec cmp_dirs(atom() | file:filename(), atom() | file:filename()) -> - {[file:filename()], [file:filename()], - [{file:filename(), file:filename()}]} - | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}. +-spec cmp_dirs(Dir1, Dir2) -> + {Only1, Only2, Different} | {'error', 'beam_lib', Reason} when + Dir1 :: atom() | file:filename(), + Dir2 :: atom() | file:filename(), + Only1 :: [file:filename()], + Only2 :: [file:filename()], + Different :: [{Filename1 :: file:filename(), Filename2 :: file:filename()}], + Reason :: {'not_a_directory', term()} | info_rsn(). cmp_dirs(Dir1, Dir2) -> catch compare_dirs(Dir1, Dir2). --spec diff_dirs(atom() | file:filename(), atom() | file:filename()) -> - 'ok' | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}. +-spec diff_dirs(Dir1, Dir2) -> 'ok' | {'error', 'beam_lib', Reason} when + Dir1 :: atom() | file:filename(), + Dir2 :: atom() | file:filename(), + Reason :: {'not_a_directory', term()} | info_rsn(). diff_dirs(Dir1, Dir2) -> catch diff_directories(Dir1, Dir2). --spec strip(beam()) -> - {'ok', {module(), beam()}} | {'error', 'beam_lib', info_rsn()}. +-spec strip(Beam1) -> + {'ok', {module(), Beam2}} | {'error', 'beam_lib', info_rsn()} when + Beam1 :: beam(), + Beam2 :: beam(). strip(FileName) -> try strip_file(FileName) catch Error -> Error end. --spec strip_files([beam()]) -> - {'ok', [{module(), beam()}]} | {'error', 'beam_lib', info_rsn()}. +-spec strip_files(Files) -> + {'ok', [{module(), Beam}]} | {'error', 'beam_lib', info_rsn()} when + Files :: [beam()], + Beam :: beam(). strip_files(Files) when is_list(Files) -> try strip_fils(Files) catch Error -> Error end. --spec strip_release(atom() | file:filename()) -> +-spec strip_release(Dir) -> {'ok', [{module(), file:filename()}]} - | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}. + | {'error', 'beam_lib', Reason} when + Dir :: atom() | file:filename(), + Reason :: {'not_a_directory', term()} | info_rsn(). strip_release(Root) -> catch strip_rel(Root). --spec version(beam()) -> - {'ok', {module(), [term()]}} | {'error', 'beam_lib', chnk_rsn()}. +-spec version(Beam) -> + {'ok', {module(), [Version :: term()]}} | + {'error', 'beam_lib', chnk_rsn()} when + Beam :: beam(). version(File) -> case catch read_chunk_data(File, [attributes]) of @@ -195,11 +218,13 @@ version(File) -> Error end. --spec md5(beam()) -> - {'ok', {module(), binary()}} | {'error', 'beam_lib', chnk_rsn()}. +-spec md5(Beam) -> + {'ok', {module(), MD5}} | {'error', 'beam_lib', chnk_rsn()} when + Beam :: beam(), + MD5 :: binary(). md5(File) -> - case catch read_significant_chunks(File) of + case catch read_significant_chunks(File, md5_chunks()) of {ok, {Module, Chunks0}} -> Chunks = filter_funtab(Chunks0), {ok, {Module, erlang:md5([C || {_Id, C} <- Chunks])}}; @@ -207,7 +232,8 @@ md5(File) -> Error end. --spec format_error(term()) -> [char() | string()]. +-spec format_error(Reason) -> io_lib:chars() when + Reason :: term(). format_error({error, Error}) -> format_error(Error); @@ -260,12 +286,15 @@ format_error(E) -> | {'debug_info', mode(), module(), file:filename()}. -type crypto_fun() :: fun((crypto_fun_arg()) -> term()). --spec crypto_key_fun(crypto_fun()) -> 'ok' | {'error', term()}. +-spec crypto_key_fun(CryptoKeyFun) -> 'ok' | {'error', Reason} when + CryptoKeyFun :: crypto_fun(), + Reason :: badfun | exists | term(). crypto_key_fun(F) -> call_crypto_server({crypto_key_fun, F}). --spec clear_crypto_key_fun() -> 'undefined' | {'ok', term()}. +-spec clear_crypto_key_fun() -> 'undefined' | {'ok', Result} when + Result :: 'undefined' | term(). clear_crypto_key_fun() -> call_crypto_server(clear_crypto_key_fun). @@ -366,7 +395,7 @@ strip_fils(Files) -> %% -> {ok, {Mod, FileName}} | {ok, {Mod, binary()}} | throw(Error) strip_file(File) -> - {ok, {Mod, Chunks}} = read_significant_chunks(File), + {ok, {Mod, Chunks}} = read_significant_chunks(File, significant_chunks()), {ok, Stripped0} = build_module(Chunks), Stripped = compress(Stripped0), case File of @@ -424,8 +453,8 @@ is_useless_chunk("CInf") -> true; is_useless_chunk(_) -> false. %% -> {ok, {Module, Chunks}} | throw(Error) -read_significant_chunks(File) -> - case read_chunk_data(File, significant_chunks(), [allow_missing_chunks]) of +read_significant_chunks(File, ChunkList) -> + case read_chunk_data(File, ChunkList, [allow_missing_chunks]) of {ok, {Module, Chunks0}} -> Mandatory = mandatory_chunks(), Chunks = filter_significant_chunks(Chunks0, Mandatory, File, Module), @@ -806,12 +835,15 @@ file_error(FileName, {error, Reason}) -> error(Reason) -> throw({error, ?MODULE, Reason}). - -%% The following chunks are significant when calculating the MD5 for a module, -%% and also the modules that must be retained when stripping a file. -%% They are listed in the order that they should be MD5:ed. +%% The following chunks must be kept when stripping a BEAM file. significant_chunks() -> + ["Line" | md5_chunks()]. + +%% The following chunks are significant when calculating the MD5 +%% for a module. They are listed in the order that they should be MD5:ed. + +md5_chunks() -> ["Atom", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT"]. %% The following chunks are mandatory in every Beam file. @@ -864,13 +896,17 @@ call_crypto_server(Req) -> gen_server:call(?CRYPTO_KEY_SERVER, Req, infinity) catch exit:{noproc,_} -> - start_crypto_server(), - erlang:yield(), - call_crypto_server(Req) + %% Not started. + call_crypto_server_1(Req); + exit:{normal,_} -> + %% The process finished just as we called it. + call_crypto_server_1(Req) end. -start_crypto_server() -> - gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []). +call_crypto_server_1(Req) -> + gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []), + erlang:yield(), + call_crypto_server(Req). -spec init([]) -> {'ok', #state{}}. diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl index f6489788b2..cb1e12ae46 100644 --- a/lib/stdlib/src/binary.erl +++ b/lib/stdlib/src/binary.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -38,11 +38,28 @@ %% Implemented in this module: -export([split/2,split/3,replace/3,replace/4]). +-opaque cp() :: tuple(). +-type part() :: {Start :: non_neg_integer(), Length :: integer()}. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% split %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec split(Subject, Pattern) -> Parts when + Subject :: binary(), + Pattern :: binary() | [binary()] | cp(), + Parts :: [binary()]. + split(H,N) -> split(H,N,[]). + +-spec split(Subject, Pattern, Options) -> Parts when + Subject :: binary(), + Pattern :: binary() | [binary()] | cp(), + Options :: [Option], + Option :: {scope, part()} | trim | global, + Parts :: [binary()]. + split(Haystack,Needles,Options) -> try {Part,Global,Trim} = get_opts_split(Options,{no,false,false}), @@ -89,8 +106,26 @@ do_split(H,[{A,B}|T],N,Trim) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% replace %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec replace(Subject, Pattern, Replacement) -> Result when + Subject :: binary(), + Pattern :: binary() | [ binary() ] | cp(), + Replacement :: binary(), + Result :: binary(). + replace(H,N,R) -> replace(H,N,R,[]). + +-spec replace(Subject, Pattern, Replacement, Options) -> Result when + Subject :: binary(), + Pattern :: binary() | [ binary() ] | cp(), + Replacement :: binary(), + Options :: [Option], + Option :: global | {scope, part()} | {insert_replaced, InsPos}, + InsPos :: OnePos | [ OnePos ], + OnePos :: non_neg_integer(), + Result :: binary(). + replace(Haystack,Needles,Replacement,Options) -> try true = is_binary(Replacement), % Make badarg instead of function clause diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl index 235ea939a8..a920921a5e 100644 --- a/lib/stdlib/src/c.erl +++ b/lib/stdlib/src/c.erl @@ -71,11 +71,16 @@ help() -> %% c(FileName) %% Compile a file/module. --spec c(file:name()) -> {'ok', module()} | 'error'. +-spec c(File) -> {'ok', Module} | 'error' when + File :: file:name(), + Module :: module(). c(File) -> c(File, []). --spec c(file:name(), [compile:option()]) -> {'ok', module()} | 'error'. +-spec c(File, Options) -> {'ok', Module} | 'error' when + File :: file:name(), + Options :: [compile:option()], + Module :: module(). c(File, Opts0) when is_list(Opts0) -> Opts = [report_errors,report_warnings|Opts0], @@ -140,7 +145,8 @@ check_load(_, Mod) -> {ok, Mod}. %% with constant c2 defined, c1=v1 (v1 must be a term!), include dir %% IDir, outdir ODir. --spec lc([erl_compile:cmd_line_arg()]) -> 'ok' | 'error'. +-spec lc(Files) -> 'ok' | 'error' when + Files :: [File :: erl_compile:cmd_line_arg()]. lc(Args) -> case catch split(Args, [], []) of @@ -205,12 +211,17 @@ make_term(Str) -> throw(error) end. --spec nc(file:name()) -> {'ok', module()} | 'error'. +-spec nc(File) -> {'ok', Module} | 'error' when + File :: file:name(), + Module :: module(). nc(File) -> nc(File, []). --spec nc(file:name(), [compile:option()] | compile:option()) -> - {'ok', module} | 'error'. +-spec nc(File, Options) -> {'ok', Module} | 'error' when + File :: file:name(), + Options :: [Option] | Option, + Option:: compile:option(), + Module :: module(). nc(File, Opts0) when is_list(Opts0) -> Opts = Opts0 ++ [report_errors, report_warnings], @@ -234,14 +245,17 @@ nc(File, Opt) when is_atom(Opt) -> %% l(Mod) %% Reload module Mod from file of same name --spec l(module()) -> code:load_ret(). +-spec l(Module) -> code:load_ret() when + Module :: module(). l(Mod) -> code:purge(Mod), code:load_file(Mod). %% Network version of l/1 -%%-spec nl(module()) -> +-spec nl(Module) -> abcast | error when + Module :: module(). + nl(Mod) -> case code:get_object_code(Mod) of {_Module, Bin, Fname} -> @@ -396,15 +410,20 @@ fetch(Key, Info) -> false -> 0 end. --spec pid(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> pid(). +-spec pid(X, Y, Z) -> pid() when + X :: non_neg_integer(), + Y :: non_neg_integer(), + Z :: non_neg_integer(). pid(X, Y, Z) -> list_to_pid("<" ++ integer_to_list(X) ++ "." ++ integer_to_list(Y) ++ "." ++ integer_to_list(Z) ++ ">"). --spec i(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> - [{atom(), term()}]. +-spec i(X, Y, Z) -> [{atom(), term()}] when + X :: non_neg_integer(), + Y :: non_neg_integer(), + Z :: non_neg_integer(). i(X, Y, Z) -> pinfo(pid(X, Y, Z)). @@ -413,7 +432,8 @@ i(X, Y, Z) -> pinfo(pid(X, Y, Z)). q() -> init:stop(). --spec bt(pid()) -> 'ok' | 'undefined'. +-spec bt(Pid) -> 'ok' | 'undefined' when + Pid :: pid(). bt(Pid) -> case catch erlang:process_display(Pid, backtrace) of @@ -476,7 +496,8 @@ bi(I) -> %% %% Short and nice form of module info %% --spec m(module()) -> 'ok'. +-spec m(Module) -> 'ok' when + Module :: module(). m(M) -> L = M:module_info(), @@ -664,7 +685,8 @@ pwd() -> ok = io:format("Cannot determine current directory\n") end. --spec cd(file:name()) -> 'ok'. +-spec cd(Dir) -> 'ok' when + Dir :: file:name(). cd(Dir) -> file:set_cwd(Dir), @@ -679,7 +701,8 @@ cd(Dir) -> ls() -> ls("."). --spec ls(file:name()) -> 'ok'. +-spec ls(Dir) -> 'ok' when + Dir :: file:name(). ls(Dir) -> case file:list_dir(Dir) of @@ -729,12 +752,19 @@ w(X) -> %% memory/[0,1] %% --spec memory() -> [{atom(), non_neg_integer()}]. +-spec memory() -> [{Type, Size}] when + Type :: atom(), + Size :: non_neg_integer(). memory() -> erlang:memory(). --spec memory(atom()) -> non_neg_integer() - ; ([atom()]) -> [{atom(), non_neg_integer()}]. +-spec memory(Type) -> Size when + Type :: atom(), + Size :: non_neg_integer() + ; (Types) -> [{Type, Size}] when + Types :: [Type], + Type :: atom(), + Size :: non_neg_integer(). memory(TypeSpec) -> erlang:memory(TypeSpec). @@ -767,7 +797,7 @@ appcall(App, M, F, Args) -> catch error:undef -> case erlang:get_stacktrace() of - [{M,F,Args}|_] -> + [{M,F,Args,_}|_] -> Arity = length(Args), io:format("Call to ~w:~w/~w in application ~w failed.\n", [M,F,Arity,App]); diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl index 33725d999c..0320e0cd0e 100644 --- a/lib/stdlib/src/calendar.erl +++ b/lib/stdlib/src/calendar.erl @@ -63,6 +63,8 @@ %% Types %%---------------------------------------------------------------------- +-export_type([date/0, time/0, datetime/0, datetime1970/0]). + -type year() :: non_neg_integer(). -type year1970() :: 1970..10000. % should probably be 1970.. -type month() :: 1..12. @@ -74,13 +76,11 @@ -type ldom() :: 28 | 29 | 30 | 31. % last day of month -type weeknum() :: 1..53. --type t_now() :: {non_neg_integer(),non_neg_integer(),non_neg_integer()}. - --type t_date() :: {year(),month(),day()}. --type t_time() :: {hour(),minute(),second()}. --type t_datetime() :: {t_date(),t_time()}. --type t_datetime1970() :: {{year1970(),month(),day()},t_time()}. --type t_yearweeknum() :: {year(),weeknum()}. +-type date() :: {year(),month(),day()}. +-type time() :: {hour(),minute(),second()}. +-type datetime() :: {date(),time()}. +-type datetime1970() :: {{year1970(),month(),day()},time()}. +-type yearweeknum() :: {year(),weeknum()}. %%---------------------------------------------------------------------- @@ -106,7 +106,11 @@ %% January 1st. %% %% df/2 catches the case Year<0 --spec date_to_gregorian_days(year(),month(),day()) -> non_neg_integer(). +-spec date_to_gregorian_days(Year, Month, Day) -> Days when + Year :: year(), + Month :: month(), + Day :: day(), + Days :: non_neg_integer(). date_to_gregorian_days(Year, Month, Day) when is_integer(Day), Day > 0 -> Last = last_day_of_the_month(Year, Month), if @@ -114,7 +118,9 @@ date_to_gregorian_days(Year, Month, Day) when is_integer(Day), Day > 0 -> dy(Year) + dm(Month) + df(Year, Month) + Day - 1 end. --spec date_to_gregorian_days(t_date()) -> non_neg_integer(). +-spec date_to_gregorian_days(Date) -> Days when + Date :: date(), + Days :: non_neg_integer(). date_to_gregorian_days({Year, Month, Day}) -> date_to_gregorian_days(Year, Month, Day). @@ -124,7 +130,9 @@ date_to_gregorian_days({Year, Month, Day}) -> %% Computes the total number of seconds starting from year 0, %% January 1st. %% --spec datetime_to_gregorian_seconds(t_datetime()) -> non_neg_integer(). +-spec datetime_to_gregorian_seconds(DateTime) -> Seconds when + DateTime :: datetime(), + Seconds :: non_neg_integer(). datetime_to_gregorian_seconds({Date, Time}) -> ?SECONDS_PER_DAY*date_to_gregorian_days(Date) + time_to_seconds(Time). @@ -135,18 +143,23 @@ datetime_to_gregorian_seconds({Date, Time}) -> %% %% Returns: 1 | .. | 7. Monday = 1, Tuesday = 2, ..., Sunday = 7. %% --spec day_of_the_week(year(), month(), day()) -> daynum(). +-spec day_of_the_week(Year, Month, Day) -> daynum() when + Year :: year(), + Month :: month(), + Day :: day(). day_of_the_week(Year, Month, Day) -> (date_to_gregorian_days(Year, Month, Day) + 5) rem 7 + 1. --spec day_of_the_week(t_date()) -> daynum(). +-spec day_of_the_week(Date) -> daynum() when + Date:: date(). day_of_the_week({Year, Month, Day}) -> day_of_the_week(Year, Month, Day). %% gregorian_days_to_date(Days) = {Year, Month, Day} %% --spec gregorian_days_to_date(non_neg_integer()) -> t_date(). +-spec gregorian_days_to_date(Days) -> date() when + Days :: non_neg_integer(). gregorian_days_to_date(Days) -> {Year, DayOfYear} = day_to_year(Days), {Month, DayOfMonth} = year_day_to_date(Year, DayOfYear), @@ -155,7 +168,8 @@ gregorian_days_to_date(Days) -> %% gregorian_seconds_to_datetime(Secs) %% --spec gregorian_seconds_to_datetime(non_neg_integer()) -> t_datetime(). +-spec gregorian_seconds_to_datetime(Seconds) -> datetime() when + Seconds :: non_neg_integer(). gregorian_seconds_to_datetime(Secs) when Secs >= 0 -> Days = Secs div ?SECONDS_PER_DAY, Rest = Secs rem ?SECONDS_PER_DAY, @@ -164,7 +178,8 @@ gregorian_seconds_to_datetime(Secs) when Secs >= 0 -> %% is_leap_year(Year) = true | false %% --spec is_leap_year(year()) -> boolean(). +-spec is_leap_year(Year) -> boolean() when + Year :: year(). is_leap_year(Y) when is_integer(Y), Y >= 0 -> is_leap_year1(Y). @@ -179,7 +194,7 @@ is_leap_year1(_) -> false. %% %% Calculates the iso week number for the current date. %% --spec iso_week_number() -> t_yearweeknum(). +-spec iso_week_number() -> yearweeknum(). iso_week_number() -> {Date, _} = local_time(), iso_week_number(Date). @@ -188,7 +203,8 @@ iso_week_number() -> %% %% Calculates the iso week number for the given date. %% --spec iso_week_number(t_date()) -> t_yearweeknum(). +-spec iso_week_number(Date) -> yearweeknum() when + Date :: date(). iso_week_number({Year, Month, Day}) -> D = date_to_gregorian_days({Year, Month, Day}), W01_1_Year = gregorian_days_of_iso_w01_1(Year), @@ -216,7 +232,10 @@ iso_week_number({Year, Month, Day}) -> %% %% Returns the number of days in a month. %% --spec last_day_of_the_month(year(), month()) -> ldom(). +-spec last_day_of_the_month(Year, Month) -> LastDay when + Year :: year(), + Month :: month(), + LastDay :: ldom(). last_day_of_the_month(Y, M) when is_integer(Y), Y >= 0 -> last_day_of_the_month1(Y, M). @@ -237,24 +256,28 @@ last_day_of_the_month1(_, M) when is_integer(M), M > 0, M < 13 -> %% local_time() %% %% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}. --spec local_time() -> t_datetime(). +-spec local_time() -> datetime(). local_time() -> erlang:localtime(). %% local_time_to_universal_time(DateTime) %% --spec local_time_to_universal_time(t_datetime1970()) -> t_datetime1970(). +-spec local_time_to_universal_time(DateTime1) -> DateTime2 when + DateTime1 :: datetime1970(), + DateTime2 :: datetime1970(). local_time_to_universal_time(DateTime) -> erlang:localtime_to_universaltime(DateTime). --spec local_time_to_universal_time(t_datetime1970(), +-spec local_time_to_universal_time(datetime1970(), 'true' | 'false' | 'undefined') -> - t_datetime1970(). + datetime1970(). local_time_to_universal_time(DateTime, IsDst) -> erlang:localtime_to_universaltime(DateTime, IsDst). --spec local_time_to_universal_time_dst(t_datetime1970()) -> [t_datetime1970()]. +-spec local_time_to_universal_time_dst(DateTime1) -> [DateTime] when + DateTime1 :: datetime1970(), + DateTime :: datetime1970(). local_time_to_universal_time_dst(DateTime) -> UtDst = erlang:localtime_to_universaltime(DateTime, true), Ut = erlang:localtime_to_universaltime(DateTime, false), @@ -282,12 +305,14 @@ local_time_to_universal_time_dst(DateTime) -> %% = MilliSec = integer() %% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}. %% --spec now_to_datetime(t_now()) -> t_datetime1970(). +-spec now_to_datetime(Now) -> datetime1970() when + Now :: erlang:timestamp(). now_to_datetime({MSec, Sec, _uSec}) -> Sec0 = MSec*1000000 + Sec + ?DAYS_FROM_0_TO_1970*?SECONDS_PER_DAY, gregorian_seconds_to_datetime(Sec0). --spec now_to_universal_time(t_now()) -> t_datetime1970(). +-spec now_to_universal_time(Now) -> datetime1970() when + Now :: erlang:timestamp(). now_to_universal_time(Now) -> now_to_datetime(Now). @@ -296,7 +321,8 @@ now_to_universal_time(Now) -> %% %% Args: Now = now() %% --spec now_to_local_time(t_now()) -> t_datetime1970(). +-spec now_to_local_time(Now) -> datetime1970() when + Now :: erlang:timestamp(). now_to_local_time({MSec, Sec, _uSec}) -> erlang:universaltime_to_localtime( now_to_universal_time({MSec, Sec, _uSec})). @@ -305,7 +331,10 @@ now_to_local_time({MSec, Sec, _uSec}) -> %% seconds_to_daystime(Secs) = {Days, {Hour, Minute, Second}} %% --spec seconds_to_daystime(integer()) -> {integer(), t_time()}. +-spec seconds_to_daystime(Seconds) -> {Days, Time} when + Seconds :: integer(), + Days :: integer(), + Time :: time(). seconds_to_daystime(Secs) -> Days0 = Secs div ?SECONDS_PER_DAY, Secs0 = Secs rem ?SECONDS_PER_DAY, @@ -323,7 +352,8 @@ seconds_to_daystime(Secs) -> %% Wraps. %% -type secs_per_day() :: 0..?SECONDS_PER_DAY. --spec seconds_to_time(secs_per_day()) -> t_time(). +-spec seconds_to_time(Seconds) -> time() when + Seconds :: secs_per_day(). seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY -> Secs0 = Secs rem ?SECONDS_PER_DAY, Hour = Secs0 div ?SECONDS_PER_HOUR, @@ -340,8 +370,11 @@ seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY -> %% Date = {Year, Month, Day}, Time = {Hour, Minute, Sec}, %% Year = Month = Day = Hour = Minute = Sec = integer() %% --type timediff() :: {integer(), t_time()}. --spec time_difference(t_datetime(), t_datetime()) -> timediff(). +-spec time_difference(T1, T2) -> {Days, Time} when + T1 :: datetime(), + T2 :: datetime(), + Days :: integer(), + Time :: time(). time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}}, {{Y2, Mo2, D2}, {H2, Mi2, S2}}) -> Secs = datetime_to_gregorian_seconds({{Y2, Mo2, D2}, {H2, Mi2, S2}}) - @@ -352,7 +385,8 @@ time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}}, %% %% time_to_seconds(Time) %% --spec time_to_seconds(t_time()) -> secs_per_day(). +-spec time_to_seconds(Time) -> secs_per_day() when + Time :: time(). time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) -> H * ?SECONDS_PER_HOUR + M * ?SECONDS_PER_MINUTE + S. @@ -361,14 +395,15 @@ time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) -> %% universal_time() %% %% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}. --spec universal_time() -> t_datetime(). +-spec universal_time() -> datetime(). universal_time() -> erlang:universaltime(). %% universal_time_to_local_time(DateTime) %% --spec universal_time_to_local_time(t_datetime()) -> t_datetime(). +-spec universal_time_to_local_time(DateTime) -> datetime() when + DateTime :: datetime1970(). universal_time_to_local_time(DateTime) -> erlang:universaltime_to_localtime(DateTime). @@ -376,7 +411,10 @@ universal_time_to_local_time(DateTime) -> %% valid_date(Year, Month, Day) = true | false %% valid_date({Year, Month, Day}) = true | false %% --spec valid_date(integer(), integer(), integer()) -> boolean(). +-spec valid_date(Year, Month, Day) -> boolean() when + Year :: integer(), + Month :: integer(), + Day :: integer(). valid_date(Y, M, D) when is_integer(Y), is_integer(M), is_integer(D) -> valid_date1(Y, M, D). @@ -386,7 +424,8 @@ valid_date1(Y, M, D) when Y >= 0, M > 0, M < 13, D > 0 -> valid_date1(_, _, _) -> false. --spec valid_date({integer(),integer(),integer()}) -> boolean(). +-spec valid_date(Date) -> boolean() when + Date :: date(). valid_date({Y, M, D}) -> valid_date(Y, M, D). diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl index 6c91f1efb7..c0f9ce34b0 100644 --- a/lib/stdlib/src/dets.erl +++ b/lib/stdlib/src/dets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -97,10 +97,6 @@ -include("dets.hrl"). --type object() :: tuple(). --type pattern() :: atom() | tuple(). --type tab_name() :: atom() | reference(). - %%% This is the implementation of the mnesia file storage. Each (non %%% ram-copy) table is maintained in a corresponding .DAT file. The %%% dat file is organized as a segmented linear hashlist. The head of @@ -179,6 +175,21 @@ %%-define(PROFILE(C), C). -define(PROFILE(C), void). +-type access() :: 'read' | 'read_write'. +-type auto_save() :: 'infinity' | non_neg_integer(). +-opaque bindings_cont() :: #dets_cont{}. +-opaque cont() :: #dets_cont{}. +-type keypos() :: pos_integer(). +-type match_spec() :: ets:match_spec(). +-type object() :: tuple(). +-type no_slots() :: non_neg_integer() | 'default'. +-opaque object_cont() :: #dets_cont{}. +-type pattern() :: atom() | tuple(). +-opaque select_cont() :: #dets_cont{}. +-type tab_name() :: term(). +-type type() :: 'bag' | 'duplicate_bag' | 'set'. +-type version() :: 8 | 9 | 'default'. + %%% Some further debug code was added in R12B-1 (stdlib-1.15.1): %%% - there is a new open_file() option 'debug'; %%% - there is a new OS environment variable 'DETS_DEBUG'; @@ -203,9 +214,13 @@ add_user(Pid, Tab, Args) -> all() -> dets_server:all(). --type cont() :: #dets_cont{}. --spec bchunk(tab_name(), 'start' | cont()) -> - {cont(), binary() | tuple()} | '$end_of_table' | {'error', term()}. +-spec bchunk(Name, Continuation) -> + {Continuation2, Data} | '$end_of_table' | {'error', Reason} when + Name :: tab_name(), + Continuation :: 'start' | cont(), + Continuation2 :: cont(), + Data :: binary() | tuple(), + Reason :: term(). bchunk(Tab, start) -> badarg(treq(Tab, {bchunk_init, Tab}), [Tab, start]); @@ -214,7 +229,9 @@ bchunk(Tab, #dets_cont{what = bchunk, tab = Tab} = State) -> bchunk(Tab, Term) -> erlang:error(badarg, [Tab, Term]). --spec close(tab_name()) -> 'ok' | {'error', term()}. +-spec close(Name) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Reason :: term(). close(Tab) -> case dets_server:close(Tab) of @@ -224,12 +241,17 @@ close(Tab) -> Reply end. --spec delete(tab_name(), term()) -> 'ok' | {'error', term()}. +-spec delete(Name, Key) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Key :: term(), + Reason :: term(). delete(Tab, Key) -> badarg(treq(Tab, {delete_key, [Key]}), [Tab, Key]). --spec delete_all_objects(tab_name()) -> 'ok' | {'error', term()}. +-spec delete_all_objects(Name) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Reason :: term(). delete_all_objects(Tab) -> case treq(Tab, delete_all_objects) of @@ -241,7 +263,10 @@ delete_all_objects(Tab) -> Reply end. --spec delete_object(tab_name(), object()) -> 'ok' | {'error', term()}. +-spec delete_object(Name, Object) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Object :: object(), + Reason :: term(). delete_object(Tab, O) -> badarg(treq(Tab, {delete_object, [O]}), [Tab, O]). @@ -264,23 +289,42 @@ fsck(Fname, Version) -> end end. --spec first(tab_name()) -> term() | '$end_of_table'. +-spec first(Name) -> Key | '$end_of_table' when + Name :: tab_name(), + Key :: term(). first(Tab) -> badarg_exit(treq(Tab, first), [Tab]). --spec foldr(fun((object(), Acc) -> Acc), Acc, tab_name()) -> Acc | {'error', term()}. +-spec foldr(Function, Acc0, Name) -> Acc | {'error', Reason} when + Name :: tab_name(), + Function :: fun((Object :: object(), AccIn) -> AccOut), + Acc0 :: term(), + Acc :: term(), + AccIn :: term(), + AccOut :: term(), + Reason :: term(). foldr(Fun, Acc, Tab) -> foldl(Fun, Acc, Tab). --spec foldl(fun((object(), Acc) -> Acc), Acc, tab_name()) -> Acc | {'error', term()}. +-spec foldl(Function, Acc0, Name) -> Acc | {'error', Reason} when + Name :: tab_name(), + Function :: fun((Object :: object(), AccIn) -> AccOut), + Acc0 :: term(), + Acc :: term(), + AccIn :: term(), + AccOut :: term(), + Reason :: term(). foldl(Fun, Acc, Tab) -> Ref = make_ref(), do_traverse(Fun, Acc, Tab, Ref). --spec from_ets(tab_name(), ets:tab()) -> 'ok' | {'error', term()}. +-spec from_ets(Name, EtsTab) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + EtsTab :: ets:tab(), + Reason :: term(). from_ets(DTab, ETab) -> ets:safe_fixtable(ETab, true), @@ -304,6 +348,15 @@ from_ets_fun(LC, ETab) -> {L, from_ets_fun(ets:select(C), ETab)} end. +-spec info(Name) -> InfoList | 'undefined' when + Name :: tab_name(), + InfoList :: [InfoTuple], + InfoTuple :: {'file_size', non_neg_integer()} + | {'filename', file:name()} + | {'keypos', keypos()} + | {'size', non_neg_integer()} + | {'type', type()}. + info(Tab) -> case catch dets_server:get_pid(Tab) of {'EXIT', _Reason} -> @@ -312,6 +365,14 @@ info(Tab) -> undefined(req(Pid, info)) end. +-spec info(Name, Item) -> Value | 'undefined' when + Name :: tab_name(), + Item :: 'access' | 'auto_save' | 'bchunk_format' + | 'hash' | 'file_size' | 'filename' | 'keypos' | 'memory' + | 'no_keys' | 'no_objects' | 'no_slots' | 'owner' | 'ram_file' + | 'safe_fixed' | 'size' | 'type' | 'version', + Value :: term(). + info(Tab, owner) -> case catch dets_server:get_pid(Tab) of Pid when is_pid(Pid) -> @@ -334,9 +395,27 @@ info(Tab, Tag) -> undefined(req(Pid, {info, Tag})) end. +-spec init_table(Name, InitFun) -> ok | {'error', Reason} when + Name :: tab_name(), + InitFun :: fun((Arg) -> Res), + Arg :: read | close, + Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(), + Reason :: term(), + Data :: binary() | tuple(). + init_table(Tab, InitFun) -> init_table(Tab, InitFun, []). +-spec init_table(Name, InitFun, Options) -> ok | {'error', Reason} when + Name :: tab_name(), + InitFun :: fun((Arg) -> Res), + Arg :: read | close, + Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(), + Options :: Option | [Option], + Option :: {min_no_slots,no_slots()} | {format,term | bchunk}, + Reason :: term(), + Data :: binary() | tuple(). + init_table(Tab, InitFun, Options) when is_function(InitFun) -> case options(Options, [format, min_no_slots]) of {badarg,_} -> @@ -350,11 +429,20 @@ init_table(Tab, InitFun, Options) when is_function(InitFun) -> init_table(Tab, InitFun, Options) -> erlang:error(badarg, [Tab, InitFun, Options]). +-spec insert(Name, Objects) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Objects :: object() | [object()], + Reason :: term(). + insert(Tab, Objs) when is_list(Objs) -> badarg(treq(Tab, {insert, Objs}), [Tab, Objs]); insert(Tab, Obj) -> badarg(treq(Tab, {insert, [Obj]}), [Tab, Obj]). +-spec insert_new(Name, Objects) -> boolean() when + Name :: tab_name(), + Objects :: object() | [object()]. + insert_new(Tab, Objs) when is_list(Objs) -> badarg(treq(Tab, {insert_new, Objs}), [Tab, Objs]); insert_new(Tab, Obj) -> @@ -366,9 +454,17 @@ internal_close(Pid) -> internal_open(Pid, Ref, Args) -> req(Pid, {internal_open, Ref, Args}). +-spec is_compatible_bchunk_format(Name, BchunkFormat) -> boolean() when + Name :: tab_name(), + BchunkFormat :: binary(). + is_compatible_bchunk_format(Tab, Term) -> badarg(treq(Tab, {is_compatible_bchunk_format, Term}), [Tab, Term]). +-spec is_dets_file(Filename) -> boolean() | {'error', Reason} when + Filename :: file:name(), + Reason :: term(). + is_dets_file(FileName) -> case catch read_file_header(FileName, read, false) of {ok, Fd, FH} -> @@ -382,6 +478,12 @@ is_dets_file(FileName) -> Other end. +-spec lookup(Name, Key) -> Objects | {'error', Reason} when + Name :: tab_name(), + Key :: term(), + Objects :: [object()], + Reason :: term(). + lookup(Tab, Key) -> badarg(treq(Tab, {lookup_keys, [Key]}), [Tab, Key]). @@ -394,19 +496,43 @@ lookup_keys(Tab, Keys) -> erlang:error(badarg, [Tab, Keys]) end. +-spec match(Name, Pattern) -> [Match] | {'error', Reason} when + Name :: tab_name(), + Pattern :: pattern(), + Match :: [term()], + Reason :: term(). + match(Tab, Pat) -> badarg(safe_match(Tab, Pat, bindings), [Tab, Pat]). +-spec match(Name, Pattern, N) -> + {[Match], Continuation} | '$end_of_table' | {'error', Reason} when + Name :: tab_name(), + Pattern :: pattern(), + N :: 'default' | non_neg_integer(), + Continuation :: bindings_cont(), + Match :: [term()], + Reason :: term(). + match(Tab, Pat, N) -> badarg(init_chunk_match(Tab, Pat, bindings, N), [Tab, Pat, N]). +-spec match(Continuation) -> + {[Match], Continuation2} | '$end_of_table' | {'error', Reason} when + Continuation :: bindings_cont(), + Continuation2 :: bindings_cont(), + Match :: [term()], + Reason :: term(). + match(State) when State#dets_cont.what =:= bindings -> badarg(chunk_match(State), [State]); match(Term) -> erlang:error(badarg, [Term]). --spec match_delete(tab_name(), pattern()) -> - non_neg_integer() | 'ok' | {'error', term()}. +-spec match_delete(Name, Pattern) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Pattern :: pattern(), + Reason :: term(). match_delete(Tab, Pat) -> badarg(match_delete(Tab, Pat, delete), [Tab, Pat]). @@ -434,23 +560,60 @@ do_match_delete(Tab, _Proc, Error, _What, _N) -> safe_fixtable(Tab, false), Error. +-spec match_object(Name, Pattern) -> Objects | {'error', Reason} when + Name :: tab_name(), + Pattern :: pattern(), + Objects :: [object()], + Reason :: term(). + match_object(Tab, Pat) -> badarg(safe_match(Tab, Pat, object), [Tab, Pat]). +-spec match_object(Name, Pattern, N) -> + {Objects, Continuation} | '$end_of_table' | {'error', Reason} when + Name :: tab_name(), + Pattern :: pattern(), + N :: 'default' | non_neg_integer(), + Continuation :: object_cont(), + Objects :: [object()], + Reason :: term(). + match_object(Tab, Pat, N) -> badarg(init_chunk_match(Tab, Pat, object, N), [Tab, Pat, N]). +-spec match_object(Continuation) -> + {Objects, Continuation2} | '$end_of_table' | {'error', Reason} when + Continuation :: object_cont(), + Continuation2 :: object_cont(), + Objects :: [object()], + Reason :: term(). + match_object(State) when State#dets_cont.what =:= object -> badarg(chunk_match(State), [State]); match_object(Term) -> erlang:error(badarg, [Term]). +-spec member(Name, Key) -> boolean() | {'error', Reason} when + Name :: tab_name(), + Key :: term(), + Reason :: term(). + member(Tab, Key) -> badarg(treq(Tab, {member, Key}), [Tab, Key]). +-spec next(Name, Key1) -> Key2 | '$end_of_table' when + Name :: tab_name(), + Key1 :: term(), + Key2 :: term(). + next(Tab, Key) -> badarg_exit(treq(Tab, {next, Key}), [Tab, Key]). +-spec open_file(Filename) -> {'ok', Reference} | {'error', Reason} when + Filename :: file:name(), + Reference :: reference(), + Reason :: term(). + %% Assuming that a file already exists, open it with the %% parameters as already specified in the file itself. %% Return a ref leading to the file. @@ -462,6 +625,22 @@ open_file(File) -> einval(Reply, [File]) end. +-spec open_file(Name, Args) -> {'ok', Name} | {'error', Reason} when + Name :: tab_name(), + Args :: [OpenArg], + OpenArg :: {'access', access()} + | {'auto_save', auto_save()} + | {'estimated_no_objects', non_neg_integer()} + | {'file', file:name()} + | {'max_no_slots', no_slots()} + | {'min_no_slots', no_slots()} + | {'keypos', keypos()} + | {'ram_file', boolean()} + | {'repair', boolean() | 'force'} + | {'type', type()} + | {'version', version()}, + Reason :: term(). + open_file(Tab, Args) when is_list(Args) -> case catch defaults(Tab, Args) of OpenArgs when is_record(OpenArgs, open_args) -> @@ -477,12 +656,21 @@ open_file(Tab, Args) when is_list(Args) -> open_file(Tab, Arg) -> open_file(Tab, [Arg]). +-spec pid2name(Pid) -> {'ok', Name} | 'undefined' when + Pid :: pid(), + Name :: tab_name(). + pid2name(Pid) -> dets_server:pid2name(Pid). remove_user(Pid, From) -> req(Pid, {close, From}). +-spec repair_continuation(Continuation, MatchSpec) -> Continuation2 when + Continuation :: select_cont(), + Continuation2 :: select_cont(), + MatchSpec :: match_spec(). + repair_continuation(#dets_cont{match_program = B}=Cont, MS) when is_binary(B) -> case ets:is_compiled_ms(B) of @@ -496,25 +684,63 @@ repair_continuation(#dets_cont{}=Cont, _MS) -> repair_continuation(T, MS) -> erlang:error(badarg, [T, MS]). +-spec safe_fixtable(Name, Fix) -> 'ok' when + Name :: tab_name(), + Fix :: boolean(). + safe_fixtable(Tab, Bool) when Bool; not Bool -> badarg(treq(Tab, {safe_fixtable, Bool}), [Tab, Bool]); safe_fixtable(Tab, Term) -> erlang:error(badarg, [Tab, Term]). +-spec select(Name, MatchSpec) -> Selection | {'error', Reason} when + Name :: tab_name(), + MatchSpec :: match_spec(), + Selection :: [term()], + Reason :: term(). + select(Tab, Pat) -> badarg(safe_match(Tab, Pat, select), [Tab, Pat]). +-spec select(Name, MatchSpec, N) -> + {Selection, Continuation} | '$end_of_table' | {'error', Reason} when + Name :: tab_name(), + MatchSpec :: match_spec(), + N :: 'default' | non_neg_integer(), + Continuation :: select_cont(), + Selection :: [term()], + Reason :: term(). + select(Tab, Pat, N) -> badarg(init_chunk_match(Tab, Pat, select, N), [Tab, Pat, N]). +-spec select(Continuation) -> + {Selection, Continuation2} | '$end_of_table' | {'error', Reason} when + Continuation :: select_cont(), + Continuation2 :: select_cont(), + Selection :: [term()], + Reason :: term(). + select(State) when State#dets_cont.what =:= select -> badarg(chunk_match(State), [State]); select(Term) -> erlang:error(badarg, [Term]). +-spec select_delete(Name, MatchSpec) -> N | {'error', Reason} when + Name :: tab_name(), + MatchSpec :: match_spec(), + N :: non_neg_integer(), + Reason :: term(). + select_delete(Tab, Pat) -> badarg(match_delete(Tab, Pat, select), [Tab, Pat]). +-spec slot(Name, I) -> '$end_of_table' | Objects | {'error', Reason} when + Name :: tab_name(), + I :: non_neg_integer(), + Objects :: [object()], + Reason :: term(). + slot(Tab, Slot) when is_integer(Slot), Slot >= 0 -> badarg(treq(Tab, {slot, Slot}), [Tab, Slot]); slot(Tab, Term) -> @@ -529,12 +755,29 @@ stop() -> istart_link(Server) -> {ok, proc_lib:spawn_link(dets, init, [self(), Server])}. +-spec sync(Name) -> 'ok' | {'error', Reason} when + Name :: tab_name(), + Reason :: term(). + sync(Tab) -> badarg(treq(Tab, sync), [Tab]). +-spec table(Name) -> QueryHandle when + Name :: tab_name(), + QueryHandle :: qlc:query_handle(). + table(Tab) -> table(Tab, []). +-spec table(Name, Options) -> QueryHandle when + Name :: tab_name(), + Options :: Option | [Option], + Option :: {'n_objects', Limit} + | {'traverse', TraverseMethod}, + Limit :: 'default' | pos_integer(), + TraverseMethod :: 'first_next' | 'select' | {'select', match_spec()}, + QueryHandle :: qlc:query_handle(). + table(Tab, Opts) -> case options(Opts, [traverse, n_objects]) of {badarg,_} -> @@ -612,6 +855,11 @@ table_info(_Tab, _) -> %% End of table/2. +-spec to_ets(Name, EtsTab) -> EtsTab | {'error', Reason} when + Name :: tab_name(), + EtsTab :: ets:tab(), + Reason :: term(). + to_ets(DTab, ETab) -> case ets:info(ETab, protection) of undefined -> @@ -621,6 +869,20 @@ to_ets(DTab, ETab) -> foldl(Fun, ETab, DTab) end. +-spec traverse(Name, Fun) -> Return | {'error', Reason} when + Name :: tab_name(), + Fun :: fun((Object) -> FunReturn), + Object :: object(), + FunReturn :: 'continue' + | {'continue', Val} + | {'done', Value} + | OtherValue, + Return :: [term()] | OtherValue, + Val :: term(), + Value :: term(), + OtherValue :: term(), + Reason :: term(). + traverse(Tab, Fun) -> Ref = make_ref(), TFun = @@ -638,6 +900,14 @@ traverse(Tab, Fun) -> end, do_traverse(TFun, [], Tab, Ref). +-spec update_counter(Name, Key, Increment) -> Result when + Name :: tab_name(), + Key :: term(), + Increment :: {Pos, Incr} | Incr, + Pos :: integer(), + Incr :: integer(), + Result :: integer(). + update_counter(Tab, Key, C) -> badarg(treq(Tab, {update_counter, Key, C}), [Tab, Key, C]). @@ -1484,17 +1754,6 @@ system_code_change(State, _Module, _OldVsn, _Extra) -> %%% Internal functions %%%---------------------------------------------------------------------- -constants(FH, FileName) -> - Version = FH#fileheader.version, - if - Version =< 8 -> - dets_v8:constants(); - Version =:= 9 -> - dets_v9:constants(); - true -> - throw({error, {not_a_dets_file, FileName}}) - end. - %% -> {ok, Fd, fileheader()} | throw(Error) read_file_header(FileName, Access, RamFile) -> BF = if @@ -1572,7 +1831,11 @@ do_bchunk_init(Head, Tab) -> {H2, {error, old_version}}; Parms -> L = dets_utils:all_allocated(H2), - C0 = #dets_cont{no_objs = default, bin = <<>>, alloc = L}, + Bin = if + L =:= <<>> -> eof; + true -> <<>> + end, + C0 = #dets_cont{no_objs = default, bin = Bin, alloc = L}, BinParms = term_to_binary(Parms), {H2, {C0#dets_cont{tab = Tab, proc = self(),what = bchunk}, [BinParms]}} @@ -2205,10 +2468,23 @@ fopen2(Fname, Tab) -> %% Fd is not always closed upon error, but exit is soon called. {ok, Fd, FH} = read_file_header(Fname, Acc, Ram), Mod = FH#fileheader.mod, - case Mod:check_file_header(FH, Fd) of - {error, not_closed} -> - io:format(user,"dets: file ~p not properly closed, " - "repairing ...~n", [Fname]), + Do = case Mod:check_file_header(FH, Fd) of + {ok, Head1, ExtraInfo} -> + Head2 = Head1#head{filename = Fname}, + try {ok, Mod:init_freelist(Head2, ExtraInfo)} + catch + throw:_ -> + {repair, " has bad free lists, repairing ..."} + end; + {error, not_closed} -> + M = " not properly closed, repairing ...", + {repair, M}; + Else -> + Else + end, + case Do of + {repair, Mess} -> + io:format(user, "dets: file ~p~s~n", [Fname, Mess]), Version = default, case fsck(Fd, Tab, Fname, FH, default, default, Version) of ok -> @@ -2216,9 +2492,9 @@ fopen2(Fname, Tab) -> Error -> throw(Error) end; - {ok, Head, ExtraInfo} -> + {ok, Head} -> open_final(Head, Fname, Acc, Ram, ?DEFAULT_CACHE, - Tab, ExtraInfo, false); + Tab, false); {error, Reason} -> throw({error, {Reason, Fname}}) end; @@ -2250,12 +2526,13 @@ fopen_existing_file(Tab, OpenArgs) -> V9 = (Version =:= 9) or (Version =:= default), MinF = (MinSlots =:= default) or (MinSlots =:= FH#fileheader.min_no_slots), MaxF = (MaxSlots =:= default) or (MaxSlots =:= FH#fileheader.max_no_slots), - Do = case (FH#fileheader.mod):check_file_header(FH, Fd) of + Mod = (FH#fileheader.mod), + Wh = case Mod:check_file_header(FH, Fd) of {ok, Head, true} when Rep =:= force, Acc =:= read_write, FH#fileheader.version =:= 9, FH#fileheader.no_colls =/= undefined, MinF, MaxF, V9 -> - {compact, Head}; + {compact, Head, true}; {ok, _Head, _Extra} when Rep =:= force, Acc =:= read -> throw({error, {access_mode, Fname}}); {ok, Head, need_compacting} when Acc =:= read -> @@ -2285,6 +2562,17 @@ fopen_existing_file(Tab, OpenArgs) -> {error, Reason} -> throw({error, {Reason, Fname}}) end, + Do = case Wh of + {Tag, Hd, Extra} when Tag =:= final; Tag =:= compact -> + Hd1 = Hd#head{filename = Fname}, + try {Tag, Mod:init_freelist(Hd1, Extra)} + catch + throw:_ -> + {repair, " has bad free lists, repairing ..."} + end; + Else -> + Else + end, case Do of _ when FH#fileheader.type =/= Type -> throw({error, {type_mismatch, Fname}}); @@ -2293,8 +2581,7 @@ fopen_existing_file(Tab, OpenArgs) -> {compact, SourceHead} -> io:format(user, "dets: file ~p is now compacted ...~n", [Fname]), {ok, NewSourceHead} = open_final(SourceHead, Fname, read, false, - ?DEFAULT_CACHE, Tab, true, - Debug), + ?DEFAULT_CACHE, Tab, Debug), case catch compact(NewSourceHead) of ok -> erlang:garbage_collect(), @@ -2314,9 +2601,9 @@ fopen_existing_file(Tab, OpenArgs) -> Version, OpenArgs); _ when FH#fileheader.version =/= Version, Version =/= default -> throw({error, {version_mismatch, Fname}}); - {final, H, EI} -> + {final, H} -> H1 = H#head{auto_save = Auto}, - open_final(H1, Fname, Acc, Ram, CacheSz, Tab, EI, Debug) + open_final(H1, Fname, Acc, Ram, CacheSz, Tab, Debug) end. do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) -> @@ -2330,19 +2617,16 @@ do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) -> end. %% -> {ok, head()} | throw(Error) -open_final(Head, Fname, Acc, Ram, CacheSz, Tab, ExtraInfo, Debug) -> +open_final(Head, Fname, Acc, Ram, CacheSz, Tab, Debug) -> Head1 = Head#head{access = Acc, ram_file = Ram, filename = Fname, name = Tab, cache = dets_utils:new_cache(CacheSz)}, init_disk_map(Head1#head.version, Tab, Debug), - Mod = Head#head.mod, - Mod:cache_segps(Head1#head.fptr, Fname, Head1#head.next), - Ftab = Mod:init_freelist(Head1, ExtraInfo), + (Head1#head.mod):cache_segps(Head1#head.fptr, Fname, Head1#head.next), check_growth(Head1), - NewHead = Head1#head{freelists = Ftab}, - {ok, NewHead}. + {ok, Head1}. %% -> {ok, head()} | throw(Error) fopen_init_file(Tab, OpenArgs) -> @@ -2869,8 +3153,12 @@ init_scan(Head, NoObjs) -> check_safe_fixtable(Head), FreeLists = dets_utils:get_freelists(Head), Base = Head#head.base, - {From, To} = dets_utils:find_next_allocated(FreeLists, Base, Base), - #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From, To, <<>>}}. + case dets_utils:find_next_allocated(FreeLists, Base, Base) of + {From, To} -> + #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From,To,<<>>}}; + none -> + #dets_cont{no_objs = NoObjs, bin = eof, alloc = <<>>} + end. check_safe_fixtable(Head) -> case (Head#head.fixed =:= false) andalso @@ -2971,18 +3259,20 @@ view(FileName) -> case catch read_file_header(FileName, read, false) of {ok, Fd, FH} -> Mod = FH#fileheader.mod, - case Mod:check_file_header(FH, Fd) of - {ok, H0, ExtraInfo} -> - Ftab = Mod:init_freelist(H0, ExtraInfo), - {_Bump, Base} = constants(FH, FileName), - H = H0#head{freelists=Ftab, base = Base}, - v_free_list(H), - Mod:v_segments(H), - file:close(Fd); - X -> - file:close(Fd), - X - end; + try Mod:check_file_header(FH, Fd) of + {ok, H0, ExtraInfo} -> + Mod = FH#fileheader.mod, + case Mod:check_file_header(FH, Fd) of + {ok, H0, ExtraInfo} -> + H = Mod:init_freelist(H0, ExtraInfo), + v_free_list(H), + Mod:v_segments(H), + ok; + X -> + X + end + after file:close(Fd) + end; X -> X end. diff --git a/lib/stdlib/src/dets.hrl b/lib/stdlib/src/dets.hrl index fbffc9d008..a3f99357a2 100644 --- a/lib/stdlib/src/dets.hrl +++ b/lib/stdlib/src/dets.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -92,6 +92,7 @@ %% Info extracted from the file header. -record(fileheader, { freelist, + fl_base, cookie, closed_properly, type, diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl index af36958c1c..3e962a1c8b 100644 --- a/lib/stdlib/src/dets_v8.erl +++ b/lib/stdlib/src/dets_v8.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ %% Dets files, implementation part. This module handles versions up to %% and including 8(c). To be called from dets.erl only. --export([constants/0, mark_dirty/1, read_file_header/2, +-export([mark_dirty/1, read_file_header/2, check_file_header/2, do_perform_save/1, initiate_file/11, init_freelist/2, fsck_input/4, bulk_input/3, output_objs/4, write_cache/1, may_grow/3, @@ -163,7 +163,7 @@ %% The 8(c) version uses a different hashing algorithm, erlang:phash %% (former versions use erlang:hash). %% Version 8(b) files are only converted to version 8(c) if repair is -%% done, so we need compatability with 8(b) for a _long_ time. +%% done, so we need compatibility with 8(b) for a _long_ time. %% %% There are known bugs due to the fact that keys and objects are %% sometimes compared (==) and sometimes matched (=:=). The version @@ -196,10 +196,6 @@ %%-define(DEBUGF(X,Y), io:format(X, Y)). -define(DEBUGF(X,Y), void). -%% {Bump} -constants() -> - {?BUMP, ?BASE}. - %% -> ok | throw({NewHead,Error}) mark_dirty(Head) -> Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}], @@ -308,8 +304,9 @@ init_freelist(Head, {convert_freelist,_Version}) -> Pos = Head#head.freelists_p, case catch prterm(Head, Pos, ?OHDSZ) of {0, _Sz, Term} -> - FreeList = lists:reverse(Term), - dets_utils:init_slots_from_old_file(FreeList, Ftab); + FreeList1 = lists:reverse(Term), + FreeList = dets_utils:init_slots_from_old_file(FreeList1, Ftab), + Head#head{freelists = FreeList, base = ?BASE}; _ -> throw({error, {bad_freelists, Head#head.filename}}) end; @@ -318,7 +315,7 @@ init_freelist(Head, _) -> Pos = Head#head.freelists_p, case catch prterm(Head, Pos, ?OHDSZ) of {0, _Sz, Term} -> - Term; + Head#head{freelists = Term, base = ?BASE}; _ -> throw({error, {bad_freelists, Head#head.filename}}) end. @@ -331,6 +328,7 @@ read_file_header(Fd, FileName) -> {ok, EOF} = dets_utils:position_close(Fd, FileName, eof), {ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4), FH = #fileheader{freelist = Freelist, + fl_base = ?BASE, cookie = Cookie, closed_properly = CP, type = dets_utils:code_to_type(Type2), @@ -413,7 +411,7 @@ check_file_header(FH, Fd) -> version = ?FILE_FORMAT_VERSION, mod = ?MODULE, bump = ?BUMP, - base = ?BASE}, + base = FH#fileheader.fl_base}, {ok, H, ExtraInfo}; Error -> Error diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl index 132af01f79..f577b4410f 100644 --- a/lib/stdlib/src/dets_v9.erl +++ b/lib/stdlib/src/dets_v9.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ %% Dets files, implementation part. This module handles version 9. %% To be called from dets.erl only. --export([constants/0, mark_dirty/1, read_file_header/2, +-export([mark_dirty/1, read_file_header/2, check_file_header/2, do_perform_save/1, initiate_file/11, prep_table_copy/9, init_freelist/2, fsck_input/4, bulk_input/3, output_objs/4, bchunk_init/2, @@ -70,6 +70,17 @@ %% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum. %% (FreelistsPointer, Cookie and ClosedProperly are not digested.) %% 128 Reserved for future versions. Initially zeros. +%% Version 9(d), introduced in R15A, has instead: +%% 112 28 counters for the buddy system sizes (as for 9(b)). +%% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum. +%% (FreelistsPointer, Cookie and ClosedProperly are not digested.) +%% 4 Base of the buddy system. +%% 0 (zero) if the base is equal to ?BASE. Compatible with R14B. +%% File size at the end of the file is RealFileSize - Base. +%% The reason for modifying file size is that when a file created +%% by R15 is read by R14 a repair takes place immediately, which +%% is acceptable when downgrading. +%% 124 Reserved for future versions. Initially zeros. %% --- %% ------------------ end of file header %% 4*256 SegmentArray Pointers. @@ -86,7 +97,7 @@ %% ----------------------------- %% ??? Free lists %% ----------------------------- -%% 4 File size, in bytes. +%% 4 File size, in bytes. See 9(d) obove. %% Before we can find an object we must find the slot where the %% object resides. Each slot is a (possibly empty) list (or chain) of @@ -177,14 +188,14 @@ %%% File header %%% --define(RESERVED, 128). % Reserved for future use. +-define(RESERVED, 124). % Reserved for future use. -define(COLL_CNTRS, (28*4)). % Counters for the buddy system. -define(MD5SZ, 16). +-define(FL_BASE, 4). --define(HEADSZ, - 56+?COLL_CNTRS+?MD5SZ). % The size of the file header, in bytes, - % not including the reserved part. +-define(HEADSZ, 56+?COLL_CNTRS % The size of the file header, in bytes, + +?MD5SZ+?FL_BASE). % not including the reserved part. -define(HEADEND, (?HEADSZ+?RESERVED)). % End of header and reserved area. -define(SEGSZ, 512). % Size of a segment, in words. SZOBJP*SEGSZP. @@ -270,10 +281,6 @@ %%-define(DEBUGF(X,Y), io:format(X, Y)). -define(DEBUGF(X,Y), void). -%% {Bump} -constants() -> - {?BUMP, ?BASE}. - %% -> ok | throw({NewHead,Error}) mark_dirty(Head) -> Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}], @@ -356,7 +363,7 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz, cache = dets_utils:new_cache(CacheSz), version = ?FILE_FORMAT_VERSION, bump = ?BUMP, - base = ?BASE, + base = ?BASE, % to be overwritten mod = ?MODULE }, @@ -378,13 +385,20 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz, {Head1, Ws1} = init_parts(Head0, 0, no_parts(Next), Zero, []), NoSegs = no_segs(Next), - {Head, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []), + {Head2, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []), Ws2 = if DoInitSegments -> WsP ++ WsI; true -> WsP end, dets_utils:pwrite(Fd, Fname, [W0 | lists:append(Ws1) ++ Ws2]), - true = hash_invars(Head), + true = hash_invars(Head2), + %% The allocations that have been made so far (parts, segments) + %% are permanent; the table will never shrink. Therefore the base + %% of the Buddy system can be set to the first free object. + %% This is used in allocate_all(), see below. + {_, Where, _} = dets_utils:alloc(Head2, ?BUMP), + NewFtab = dets_utils:init_alloc(Where), + Head = Head2#head{freelists = NewFtab, base = Where}, {ok, Head}. %% Returns a power of two not less than 256. @@ -451,8 +465,9 @@ read_file_header(Fd, FileName) -> Version:32, M:32, Next:32, Kp:32, NoObjects:32, NoKeys:32, MinNoSlots:32, MaxNoSlots:32, HashMethod:32, N:32, NoCollsB:?COLL_CNTRS/binary, - MD5:?MD5SZ/binary>> = Bin, - <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-12)/binary,_/binary>> = Bin, + MD5:?MD5SZ/binary, FlBase:32>> = Bin, + <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-?FL_BASE-12)/binary, + _/binary>> = Bin, {ok, EOF} = dets_utils:position_close(Fd, FileName, eof), {ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4), {CL, <<>>} = lists:foldl(fun(LSz, {Acc,<<NN:32,R/binary>>}) -> @@ -468,8 +483,12 @@ read_file_header(Fd, FileName) -> true -> lists:reverse(CL) end, - + Base = case FlBase of + 0 -> ?BASE; + _ -> FlBase + end, FH = #fileheader{freelist = FreeList, + fl_base = Base, cookie = Cookie, closed_properly = CP, type = dets_utils:code_to_type(Type2), @@ -486,7 +505,7 @@ read_file_header(Fd, FileName) -> read_md5 = MD5, has_md5 = <<0:?MD5SZ/unit:8>> =/= MD5, md5 = erlang:md5(MD5DigestedPart), - trailer = FileSize, + trailer = FileSize + FlBase, eof = EOF, n = N, mod = ?MODULE}, @@ -544,7 +563,7 @@ check_file_header(FH, Fd) -> version = ?FILE_FORMAT_VERSION, mod = ?MODULE, bump = ?BUMP, - base = ?BASE}, + base = FH#fileheader.fl_base}, {ok, H, ExtraInfo}; Error -> Error @@ -1185,41 +1204,25 @@ write_loop(Head, BytesToWrite, Bin) -> write_loop(Head, BytesToWrite, SmallBin). %% By allocating bigger objects before smaller ones, holes in the -%% buddy system memory map are avoided. Unfortunately, the segments -%% are always allocated first, so if there are objects bigger than a -%% segment, there is a hole to handle. (Haven't considered placing the -%% segments among other objects of the same size.) +%% buddy system memory map are avoided. allocate_all_objects(Head, SizeT) -> DTL = lists:reverse(lists:keysort(1, ets:tab2list(SizeT))), MaxSz = element(1, hd(DTL)), - SegSize = ?ACTUAL_SEG_SIZE, - {Head1, HSz, HN, HA} = alloc_hole(MaxSz, Head, SegSize), - {Head2, NL} = allocate_all(Head1, DTL, []), + {Head1, NL} = allocate_all(Head, DTL, []), %% Find the position that will be the end of the file by allocating %% a minimal object. - {_Head, EndOfFile, _} = dets_utils:alloc(Head2, ?BUMP), - Head3 = free_hole(Head2, HSz, HN, HA), - NewHead = Head3#head{maxobjsize = max_objsize(Head3#head.no_collections)}, + {_Head, EndOfFile, _} = dets_utils:alloc(Head1, ?BUMP), + NewHead = Head1#head{maxobjsize = max_objsize(Head1#head.no_collections)}, {NewHead, NL, MaxSz, EndOfFile}. -alloc_hole(LSize, Head, SegSz) when ?POW(LSize-1) > SegSz -> - Size = ?POW(LSize-1), - {_, SegAddr, _} = dets_utils:alloc(Head, adjsz(SegSz)), - {_, Addr, _} = dets_utils:alloc(Head, adjsz(Size)), - N = (Addr - SegAddr) div SegSz, - Head1 = dets_utils:alloc_many(Head, SegSz, N, SegAddr), - {Head1, SegSz, N, SegAddr}; -alloc_hole(_MaxSz, Head, _SegSz) -> - {Head, 0, 0, 0}. - -free_hole(Head, _Size, 0, _Addr) -> - Head; -free_hole(Head, Size, N, Addr) -> - {Head1, _} = dets_utils:free(Head, Addr, adjsz(Size)), - free_hole(Head1, Size, N-1, Addr+Size). - %% One (temporary) file for each buddy size, write all objects of that %% size to the file. +%% +%% Before R15 a "hole" was needed before the first bucket if the size +%% of the biggest bucket was greater than the size of a segment. The +%% hole proved to be a problem with almost full tables with huge +%% buckets. Since R15 the hole is no longer needed due to the fact +%% that the base of the Buddy system is flexible. allocate_all(Head, [{?FSCK_SEGMENT,_,Data,_}], L) -> %% And one file for the segments... %% Note that space for the array parts and the segments has @@ -1593,23 +1596,28 @@ do_perform_save(H) -> H1 = H#head{freelists_p = FreeListsPointer}, {FLW, FLSize} = free_lists_to_file(H1), FileSize = FreeListsPointer + FLSize + 4, - ok = dets_utils:write(H1, [FLW | <<FileSize:32>>]), + AdjustedFileSize = case H#head.base of + ?BASE -> FileSize; + Base -> FileSize - Base + end, + ok = dets_utils:write(H1, [FLW | <<AdjustedFileSize:32>>]), FileHeader = file_header(H1, FreeListsPointer, ?CLOSED_PROPERLY), case dets_utils:debug_mode() of true -> - TmpHead = H1#head{freelists = init_freelist(H1, true), - fixed = false}, + TmpHead0 = init_freelist(H1#head{fixed = false}, true), + TmpHead = TmpHead0#head{base = H1#head.base}, case catch dets_utils:all_allocated_as_list(TmpHead) =:= dets_utils:all_allocated_as_list(H1) - of + of true -> dets_utils:pwrite(H1, [{0, FileHeader}]); _ -> + throw( dets_utils:corrupt_reason(H1, {failed_to_save_free_lists, FreeListsPointer, TmpHead#head.freelists, - H1#head.freelists}) + H1#head.freelists})) end; false -> dets_utils:pwrite(H1, [{0, FileHeader}]) @@ -1648,7 +1656,11 @@ file_header(Head, FreeListsPointer, ClosedProperly, NoColls) -> true -> erlang:md5(DigH); false -> <<0:?MD5SZ/unit:8>> end, - [H1, DigH, MD5 | <<0:?RESERVED/unit:8>>]. + Base = case Head#head.base of + ?BASE -> <<0:32>>; + FlBase -> <<FlBase:32>> + end, + [H1, DigH, MD5, Base | <<0:?RESERVED/unit:8>>]. %% Going through some trouble to avoid creating one single binary for %% the free lists. If the free lists are huge, binary_to_term and @@ -1695,8 +1707,8 @@ free_lists_from_file(H, Pos) -> case catch bin_to_tree([], H, start, FL, -1, []) of {'EXIT', _} -> throw({error, {bad_freelists, H#head.filename}}); - Reply -> - Reply + Ftab -> + H#head{freelists = Ftab, base = ?BASE} end. bin_to_tree(Bin, H, LastPos, Ftab, A0, L) -> diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl index 7e51141098..2e9eba4bfa 100644 --- a/lib/stdlib/src/dict.erl +++ b/lib/stdlib/src/dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -80,7 +80,9 @@ new() -> Empty = mk_seg(?seg_size), #dict{empty=Empty,segs={Empty}}. --spec is_key(term(), dict()) -> boolean(). +-spec is_key(Key, Dict) -> boolean() when + Key :: term(), + Dict :: dict(). is_key(Key, D) -> Slot = get_slot(D, Key), @@ -91,21 +93,29 @@ find_key(K, [?kv(K,_Val)|_]) -> true; find_key(K, [_|Bkt]) -> find_key(K, Bkt); find_key(_, []) -> false. --spec to_list(dict()) -> [{term(), term()}]. +-spec to_list(Dict) -> List when + Dict :: dict(), + List :: [{Key :: term(), Value :: term()}]. to_list(D) -> fold(fun (Key, Val, List) -> [{Key,Val}|List] end, [], D). --spec from_list([{term(), term()}]) -> dict(). +-spec from_list(List) -> Dict when + List :: [{Key :: term(), Value :: term()}], + Dict :: dict(). from_list(L) -> lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, new(), L). --spec size(dict()) -> non_neg_integer(). +-spec size(Dict) -> non_neg_integer() when + Dict :: dict(). size(#dict{size=N}) when is_integer(N), N >= 0 -> N. --spec fetch(term(), dict()) -> term(). +-spec fetch(Key, Dict) -> Value when + Key :: term(), + Dict :: dict(), + Value :: term(). fetch(Key, D) -> Slot = get_slot(D, Key), @@ -119,7 +129,10 @@ fetch_val(K, [?kv(K,Val)|_]) -> Val; fetch_val(K, [_|Bkt]) -> fetch_val(K, Bkt); fetch_val(_, []) -> throw(badarg). --spec find(term(), dict()) -> {'ok', term()} | 'error'. +-spec find(Key, Dict) -> {'ok', Value} | 'error' when + Key :: term(), + Dict :: dict(), + Value :: term(). find(Key, D) -> Slot = get_slot(D, Key), @@ -130,12 +143,17 @@ find_val(K, [?kv(K,Val)|_]) -> {ok,Val}; find_val(K, [_|Bkt]) -> find_val(K, Bkt); find_val(_, []) -> error. --spec fetch_keys(dict()) -> [term()]. +-spec fetch_keys(Dict) -> Keys when + Dict :: dict(), + Keys :: [term()]. fetch_keys(D) -> fold(fun (Key, _Val, Keys) -> [Key|Keys] end, [], D). --spec erase(term(), dict()) -> dict(). +-spec erase(Key, Dict1) -> Dict2 when + Key :: term(), + Dict1 :: dict(), + Dict2 :: dict(). %% Erase all elements with key Key. erase(Key, D0) -> @@ -150,7 +168,11 @@ erase_key(Key, [E|Bkt0]) -> {[E|Bkt1],Dc}; erase_key(_, []) -> {[],0}. --spec store(term(), term(), dict()) -> dict(). +-spec store(Key, Value, Dict1) -> Dict2 when + Key :: term(), + Value :: term(), + Dict1 :: dict(), + Dict2 :: dict(). store(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -166,7 +188,11 @@ store_bkt_val(Key, New, [Other|Bkt0]) -> {[Other|Bkt1],Ic}; store_bkt_val(Key, New, []) -> {[?kv(Key,New)],1}. --spec append(term(), term(), dict()) -> dict(). +-spec append(Key, Value, Dict1) -> Dict2 when + Key :: term(), + Value :: term(), + Dict1 :: dict(), + Dict2 :: dict(). append(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -182,7 +208,11 @@ append_bkt(Key, Val, [Other|Bkt0]) -> {[Other|Bkt1],Ic}; append_bkt(Key, Val, []) -> {[?kv(Key,[Val])],1}. --spec append_list(term(), [term()], dict()) -> dict(). +-spec append_list(Key, ValList, Dict1) -> Dict2 when + Key :: term(), + ValList :: [Value :: term()], + Dict1 :: dict(), + Dict2 :: dict(). append_list(Key, L, D0) -> Slot = get_slot(D0, Key), @@ -252,7 +282,11 @@ app_list_bkt(Key, L, []) -> {[?kv(Key,L)],1}. %% {Bkt1,Dc} = on_key_bkt(Key, F, Bkt0), %% {[Other|Bkt1],Dc}. --spec update(term(), fun((term()) -> term()), dict()) -> dict(). +-spec update(Key, Fun, Dict1) -> Dict2 when + Key :: term(), + Fun :: fun((Value1 :: term()) -> Value2 :: term()), + Dict1 :: dict(), + Dict2 :: dict(). update(Key, F, D0) -> Slot = get_slot(D0, Key), @@ -271,7 +305,12 @@ update_bkt(Key, F, [Other|Bkt0]) -> update_bkt(_Key, _F, []) -> throw(badarg). --spec update(term(), fun((term()) -> term()), term(), dict()) -> dict(). +-spec update(Key, Fun, Initial, Dict1) -> Dict2 when + Key :: term(), + Initial :: term(), + Fun :: fun((Value1 :: term()) -> Value2 :: term()), + Dict1 :: dict(), + Dict2 :: dict(). update(Key, F, Init, D0) -> Slot = get_slot(D0, Key), @@ -286,7 +325,11 @@ update_bkt(Key, F, I, [Other|Bkt0]) -> {[Other|Bkt1],Ic}; update_bkt(Key, F, I, []) when is_function(F, 1) -> {[?kv(Key,I)],1}. --spec update_counter(term(), number(), dict()) -> dict(). +-spec update_counter(Key, Increment, Dict1) -> Dict2 when + Key :: term(), + Increment :: number(), + Dict1 :: dict(), + Dict2 :: dict(). update_counter(Key, Incr, D0) when is_number(Incr) -> Slot = get_slot(D0, Key), @@ -301,20 +344,38 @@ counter_bkt(Key, I, [Other|Bkt0]) -> {[Other|Bkt1],Ic}; counter_bkt(Key, I, []) -> {[?kv(Key,I)],1}. --spec fold(fun((term(), term(), term()) -> term()), term(), dict()) -> term(). +-spec fold(Fun, Acc0, Dict) -> Acc1 when + Fun :: fun((Key, Value, AccIn) -> AccOut), + Key :: term(), + Value :: term(), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + Dict :: dict(). %% Fold function Fun over all "bags" in Table and return Accumulator. fold(F, Acc, D) -> fold_dict(F, Acc, D). --spec map(fun((term(), term()) -> term()), dict()) -> dict(). +-spec map(Fun, Dict1) -> Dict2 when + Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()), + Dict1 :: dict(), + Dict2 :: dict(). map(F, D) -> map_dict(F, D). --spec filter(fun((term(), term()) -> boolean()), dict()) -> dict(). +-spec filter(Pred, Dict1) -> Dict2 when + Pred :: fun((Key :: term(), Value :: term()) -> boolean()), + Dict1 :: dict(), + Dict2 :: dict(). filter(F, D) -> filter_dict(F, D). --spec merge(fun((term(), term(), term()) -> term()), dict(), dict()) -> dict(). +-spec merge(Fun, Dict1, Dict2) -> Dict3 when + Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()), + Dict1 :: dict(), + Dict2 :: dict(), + Dict3 :: dict(). merge(F, D1, D2) when D1#dict.size < D2#dict.size -> fold_dict(fun (K, V1, D) -> diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl index 5edc868a94..e3f87d2c57 100644 --- a/lib/stdlib/src/digraph.erl +++ b/lib/stdlib/src/digraph.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -53,7 +53,8 @@ -type label() :: term(). -type vertex() :: term(). --type add_edge_err_rsn() :: {'bad_edge', [vertex()]} | {'bad_vertex', vertex()}. +-type add_edge_err_rsn() :: {'bad_edge', Path :: [vertex()]} + | {'bad_vertex', V :: vertex()}. %% %% Type is a list of @@ -70,7 +71,8 @@ new() -> new([]). --spec new([d_type()]) -> digraph(). +-spec new(Type) -> digraph() when + Type :: [d_type()]. new(Type) -> case check_type(Type, protected, []) of @@ -113,16 +115,20 @@ set_type([], G) -> G. %% Data access functions --spec delete(digraph()) -> 'true'. +-spec delete(G) -> 'true' when + G :: digraph(). delete(G) -> ets:delete(G#digraph.vtab), ets:delete(G#digraph.etab), ets:delete(G#digraph.ntab). --spec info(digraph()) -> [{'cyclicity', d_cyclicity()} | - {'memory', non_neg_integer()} | - {'protection', d_protection()}]. +-spec info(G) -> InfoList when + G :: digraph(), + InfoList :: [{'cyclicity', Cyclicity :: d_cyclicity()} | + {'memory', NoWords :: non_neg_integer()} | + {'protection', Protection :: d_protection()}]. + info(G) -> VT = G#digraph.vtab, ET = G#digraph.etab, @@ -135,32 +141,45 @@ info(G) -> Memory = ets:info(VT, memory) + ets:info(ET, memory) + ets:info(NT, memory), [{cyclicity, Cyclicity}, {memory, Memory}, {protection, Protection}]. --spec add_vertex(digraph()) -> vertex(). +-spec add_vertex(G) -> vertex() when + G :: digraph(). add_vertex(G) -> do_add_vertex({new_vertex_id(G), []}, G). --spec add_vertex(digraph(), vertex()) -> vertex(). +-spec add_vertex(G, V) -> vertex() when + G :: digraph(), + V :: vertex(). add_vertex(G, V) -> do_add_vertex({V, []}, G). --spec add_vertex(digraph(), vertex(), label()) -> vertex(). +-spec add_vertex(G, V, Label) -> vertex() when + G :: digraph(), + V :: vertex(), + Label :: label(). add_vertex(G, V, D) -> do_add_vertex({V, D}, G). --spec del_vertex(digraph(), vertex()) -> 'true'. +-spec del_vertex(G, V) -> 'true' when + G :: digraph(), + V :: vertex(). del_vertex(G, V) -> do_del_vertex(V, G). --spec del_vertices(digraph(), [vertex()]) -> 'true'. +-spec del_vertices(G, Vertices) -> 'true' when + G :: digraph(), + Vertices :: [vertex()]. del_vertices(G, Vs) -> do_del_vertices(Vs, G). --spec vertex(digraph(), vertex()) -> {vertex(), label()} | 'false'. +-spec vertex(G, V) -> {V, Label} | 'false' when + G :: digraph(), + V :: vertex(), + Label :: label(). vertex(G, V) -> case ets:lookup(G#digraph.vtab, V) of @@ -168,12 +187,15 @@ vertex(G, V) -> [Vertex] -> Vertex end. --spec no_vertices(digraph()) -> non_neg_integer(). +-spec no_vertices(G) -> non_neg_integer() when + G :: digraph(). no_vertices(G) -> ets:info(G#digraph.vtab, size). --spec vertices(digraph()) -> [vertex()]. +-spec vertices(G) -> Vertices when + G :: digraph(), + Vertices :: [vertex()]. vertices(G) -> ets:select(G#digraph.vtab, [{{'$1', '_'}, [], ['$1']}]). @@ -188,85 +210,125 @@ source_vertices(G) -> sink_vertices(G) -> collect_vertices(G, out). --spec in_degree(digraph(), vertex()) -> non_neg_integer(). +-spec in_degree(G, V) -> non_neg_integer() when + G :: digraph(), + V :: vertex(). in_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {in, V})). --spec in_neighbours(digraph(), vertex()) -> [vertex()]. +-spec in_neighbours(G, V) -> Vertex when + G :: digraph(), + V :: vertex(), + Vertex :: [vertex()]. in_neighbours(G, V) -> ET = G#digraph.etab, NT = G#digraph.ntab, collect_elems(ets:lookup(NT, {in, V}), ET, 2). --spec in_edges(digraph(), vertex()) -> [edge()]. +-spec in_edges(G, V) -> Edges when + G :: digraph(), + V :: vertex(), + Edges :: [edge()]. in_edges(G, V) -> ets:select(G#digraph.ntab, [{{{in, V}, '$1'}, [], ['$1']}]). --spec out_degree(digraph(), vertex()) -> non_neg_integer(). +-spec out_degree(G, V) -> non_neg_integer() when + G :: digraph(), + V :: vertex(). out_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {out, V})). --spec out_neighbours(digraph(), vertex()) -> [vertex()]. +-spec out_neighbours(G, V) -> Vertices when + G :: digraph(), + V :: vertex(), + Vertices :: [vertex()]. out_neighbours(G, V) -> ET = G#digraph.etab, NT = G#digraph.ntab, collect_elems(ets:lookup(NT, {out, V}), ET, 3). --spec out_edges(digraph(), vertex()) -> [edge()]. +-spec out_edges(G, V) -> Edges when + G :: digraph(), + V :: vertex(), + Edges :: [edge()]. out_edges(G, V) -> ets:select(G#digraph.ntab, [{{{out, V}, '$1'}, [], ['$1']}]). --spec add_edge(digraph(), vertex(), vertex()) -> - edge() | {'error', add_edge_err_rsn()}. +-spec add_edge(G, V1, V2) -> edge() | {'error', add_edge_err_rsn()} when + G :: digraph(), + V1 :: vertex(), + V2 :: vertex(). add_edge(G, V1, V2) -> do_add_edge({new_edge_id(G), V1, V2, []}, G). --spec add_edge(digraph(), vertex(), vertex(), label()) -> - edge() | {'error', add_edge_err_rsn()}. +-spec add_edge(G, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when + G :: digraph(), + V1 :: vertex(), + V2 :: vertex(), + Label :: label(). add_edge(G, V1, V2, D) -> do_add_edge({new_edge_id(G), V1, V2, D}, G). --spec add_edge(digraph(), edge(), vertex(), vertex(), label()) -> - edge() | {'error', add_edge_err_rsn()}. +-spec add_edge(G, E, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when + G :: digraph(), + E :: edge(), + V1 :: vertex(), + V2 :: vertex(), + Label :: label(). add_edge(G, E, V1, V2, D) -> do_add_edge({E, V1, V2, D}, G). --spec del_edge(digraph(), edge()) -> 'true'. +-spec del_edge(G, E) -> 'true' when + G :: digraph(), + E :: edge(). del_edge(G, E) -> do_del_edges([E], G). --spec del_edges(digraph(), [edge()]) -> 'true'. +-spec del_edges(G, Edges) -> 'true' when + G :: digraph(), + Edges :: [edge()]. del_edges(G, Es) -> do_del_edges(Es, G). --spec no_edges(digraph()) -> non_neg_integer(). +-spec no_edges(G) -> non_neg_integer() when + G :: digraph(). no_edges(G) -> ets:info(G#digraph.etab, size). --spec edges(digraph()) -> [edge()]. +-spec edges(G) -> Edges when + G :: digraph(), + Edges :: [edge()]. edges(G) -> ets:select(G#digraph.etab, [{{'$1', '_', '_', '_'}, [], ['$1']}]). --spec edges(digraph(), vertex()) -> [edge()]. +-spec edges(G, V) -> Edges when + G :: digraph(), + V :: vertex(), + Edges :: [edge()]. edges(G, V) -> ets:select(G#digraph.ntab, [{{{out, V},'$1'}, [], ['$1']}, {{{in, V}, '$1'}, [], ['$1']}]). --spec edge(digraph(), edge()) -> {edge(),vertex(),vertex(),label()} | 'false'. +-spec edge(G, E) -> {E, V1, V2, Label} | 'false' when + G :: digraph(), + E :: edge(), + V1 :: vertex(), + V2 :: vertex(), + Label :: label(). edge(G, E) -> case ets:lookup(G#digraph.etab,E) of @@ -277,7 +339,7 @@ edge(G, E) -> %% %% Generate a "unique" edge identifier (relative to this graph) %% --spec new_edge_id(digraph()) -> nonempty_improper_list('$e', non_neg_integer()). +-spec new_edge_id(digraph()) -> edge(). new_edge_id(G) -> NT = G#digraph.ntab, @@ -289,7 +351,7 @@ new_edge_id(G) -> %% %% Generate a "unique" vertex identifier (relative to this graph) %% --spec new_vertex_id(digraph()) -> nonempty_improper_list('$v', non_neg_integer()). +-spec new_vertex_id(digraph()) -> vertex(). new_vertex_id(G) -> NT = G#digraph.ntab, @@ -444,7 +506,10 @@ acyclic_add_edge(E, V1, V2, Label, G) -> %% Delete all paths from vertex V1 to vertex V2 %% --spec del_path(digraph(), vertex(), vertex()) -> 'true'. +-spec del_path(G, V1, V2) -> 'true' when + G :: digraph(), + V1 :: vertex(), + V2 :: vertex(). del_path(G, V1, V2) -> case get_path(G, V1, V2) of @@ -463,7 +528,10 @@ del_path(G, V1, V2) -> %% been searched. %% --spec get_cycle(digraph(), vertex()) -> [vertex(),...] | 'false'. +-spec get_cycle(G, V) -> Vertices | 'false' when + G :: digraph(), + V :: vertex(), + Vertices :: [vertex(),...]. get_cycle(G, V) -> case one_path(out_neighbours(G, V), V, [], [V], [V], 2, G, 1) of @@ -481,7 +549,11 @@ get_cycle(G, V) -> %% if no path exists false is returned %% --spec get_path(digraph(), vertex(), vertex()) -> [vertex(),...] | 'false'. +-spec get_path(G, V1, V2) -> Vertices | 'false' when + G :: digraph(), + V1 :: vertex(), + V2 :: vertex(), + Vertices :: [vertex(),...]. get_path(G, V1, V2) -> one_path(out_neighbours(G, V1), V2, [], [V1], [V1], 1, G, 1). @@ -516,7 +588,10 @@ one_path([], _, [], _, _, _, _, _Counter) -> false. %% Like get_cycle/2, but a cycle of length one is preferred. %% --spec get_short_cycle(digraph(), vertex()) -> [vertex(),...] | 'false'. +-spec get_short_cycle(G, V) -> Vertices | 'false' when + G :: digraph(), + V :: vertex(), + Vertices :: [vertex(),...]. get_short_cycle(G, V) -> get_short_path(G, V, V). @@ -526,7 +601,11 @@ get_short_cycle(G, V) -> %% to find a short path. %% --spec get_short_path(digraph(), vertex(), vertex()) -> [vertex(),...] | 'false'. +-spec get_short_path(G, V1, V2) -> Vertices | 'false' when + G :: digraph(), + V1 :: vertex(), + V2 :: vertex(), + Vertices :: [vertex(),...]. get_short_path(G, V1, V2) -> T = new(), diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl index 080cae4742..e221be15a1 100644 --- a/lib/stdlib/src/digraph_utils.erl +++ b/lib/stdlib/src/digraph_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -38,48 +38,66 @@ %% A convenient type alias %% --type vertices() :: [digraph:vertex()]. - %% %% Exported functions %% --spec components(digraph()) -> vertices(). +-spec components(Digraph) -> [Component] when + Digraph :: digraph(), + Component :: [digraph:vertex()]. components(G) -> forest(G, fun inout/3). --spec strong_components(digraph()) -> vertices(). +-spec strong_components(Digraph) -> [StrongComponent] when + Digraph :: digraph(), + StrongComponent :: [digraph:vertex()]. strong_components(G) -> forest(G, fun in/3, revpostorder(G)). --spec cyclic_strong_components(digraph()) -> vertices(). +-spec cyclic_strong_components(Digraph) -> [StrongComponent] when + Digraph :: digraph(), + StrongComponent :: [digraph:vertex()]. cyclic_strong_components(G) -> remove_singletons(strong_components(G), G, []). --spec reachable(vertices(), digraph()) -> vertices(). +-spec reachable(Vertices, Digraph) -> Reachable when + Digraph :: digraph(), + Vertices :: [digraph:vertex()], + Reachable :: [digraph:vertex()]. reachable(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, first)). --spec reachable_neighbours(vertices(), digraph()) -> vertices(). +-spec reachable_neighbours(Vertices, Digraph) -> Reachable when + Digraph :: digraph(), + Vertices :: [digraph:vertex()], + Reachable :: [digraph:vertex()]. reachable_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, not_first)). --spec reaching(vertices(), digraph()) -> vertices(). +-spec reaching(Vertices, Digraph) -> Reaching when + Digraph :: digraph(), + Vertices :: [digraph:vertex()], + Reaching :: [digraph:vertex()]. reaching(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, first)). --spec reaching_neighbours(vertices(), digraph()) -> vertices(). +-spec reaching_neighbours(Vertices, Digraph) -> Reaching when + Digraph :: digraph(), + Vertices :: [digraph:vertex()], + Reaching :: [digraph:vertex()]. reaching_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, not_first)). --spec topsort(digraph()) -> vertices() | 'false'. +-spec topsort(Digraph) -> Vertices | 'false' when + Digraph :: digraph(), + Vertices :: [digraph:vertex()]. topsort(G) -> L = revpostorder(G), @@ -88,12 +106,15 @@ topsort(G) -> false -> false end. --spec is_acyclic(digraph()) -> boolean(). +-spec is_acyclic(Digraph) -> boolean() when + Digraph :: digraph(). is_acyclic(G) -> loop_vertices(G) =:= [] andalso topsort(G) =/= false. --spec arborescence_root(digraph()) -> 'no' | {'yes', digraph:vertex()}. +-spec arborescence_root(Digraph) -> 'no' | {'yes', Root} when + Digraph :: digraph(), + Root :: digraph:vertex(). arborescence_root(G) -> case digraph:no_edges(G) =:= digraph:no_vertices(G) - 1 of @@ -114,23 +135,30 @@ arborescence_root(G) -> no end. --spec is_arborescence(digraph()) -> boolean(). +-spec is_arborescence(Digraph) -> boolean() when + Digraph :: digraph(). is_arborescence(G) -> arborescence_root(G) =/= no. --spec is_tree(digraph()) -> boolean(). +-spec is_tree(Digraph) -> boolean() when + Digraph :: digraph(). is_tree(G) -> (digraph:no_edges(G) =:= digraph:no_vertices(G) - 1) andalso (length(components(G)) =:= 1). --spec loop_vertices(digraph()) -> vertices(). +-spec loop_vertices(Digraph) -> Vertices when + Digraph :: digraph(), + Vertices :: [digraph:vertex()]. loop_vertices(G) -> [V || V <- digraph:vertices(G), is_reflexive_vertex(V, G)]. --spec subgraph(digraph(), vertices()) -> digraph(). +-spec subgraph(Digraph, Vertices) -> SubGraph when + Digraph :: digraph(), + Vertices :: [digraph:vertex()], + SubGraph :: digraph(). subgraph(G, Vs) -> try @@ -140,10 +168,12 @@ subgraph(G, Vs) -> erlang:error(badarg) end. --type option() :: {'type', 'inherit' | [digraph:d_type()]} - | {'keep_labels', boolean()}. - --spec subgraph(digraph(), vertices(), [option()]) -> digraph(). +-spec subgraph(Digraph, Vertices, Options) -> SubGraph when + Digraph :: digraph(), + SubGraph :: digraph(), + Vertices :: [digraph:vertex()], + Options :: [{'type', SubgraphType} | {'keep_labels', boolean()}], + SubgraphType :: 'inherit' | [digraph:d_type()]. subgraph(G, Vs, Opts) -> try @@ -153,7 +183,9 @@ subgraph(G, Vs, Opts) -> erlang:error(badarg) end. --spec condensation(digraph()) -> digraph(). +-spec condensation(Digraph) -> CondensedDigraph when + Digraph :: digraph(), + CondensedDigraph :: digraph(). condensation(G) -> SCs = strong_components(G), @@ -176,12 +208,16 @@ condensation(G) -> ets:delete(I2C), SCG. --spec preorder(digraph()) -> vertices(). +-spec preorder(Digraph) -> Vertices when + Digraph :: digraph(), + Vertices :: [digraph:vertex()]. preorder(G) -> lists:reverse(revpreorder(G)). --spec postorder(digraph()) -> vertices(). +-spec postorder(Digraph) -> Vertices when + Digraph :: digraph(), + Vertices :: [digraph:vertex()]. postorder(G) -> lists:reverse(revpostorder(G)). diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index e5ccaddbb4..230a4a0612 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -29,6 +29,7 @@ %%------------------------------------------------------------------------ -type macros() :: [{atom(), term()}]. +-type epp_handle() :: pid(). %% Epp state record. -record(epp, {file, %Current file @@ -61,14 +62,23 @@ %% parse_file(FileName, IncludePath, PreDefMacros) %% macro_defs(Epp) --spec open(file:name(), [file:name()]) -> - {'ok', pid()} | {'error', term()}. +-spec open(FileName, IncludePath) -> + {'ok', Epp} | {'error', ErrorDescriptor} when + FileName :: file:name(), + IncludePath :: [DirectoryName :: file:name()], + Epp :: epp_handle(), + ErrorDescriptor :: term(). open(Name, Path) -> open(Name, Path, []). --spec open(file:name(), [file:name()], macros()) -> - {'ok', pid()} | {'error', term()}. +-spec open(FileName, IncludePath, PredefMacros) -> + {'ok', Epp} | {'error', ErrorDescriptor} when + FileName :: file:name(), + IncludePath :: [DirectoryName :: file:name()], + PredefMacros :: macros(), + Epp :: epp_handle(), + ErrorDescriptor :: term(). open(Name, Path, Pdm) -> Self = self(), @@ -80,7 +90,8 @@ open(Name, File, StartLocation, Path, Pdm) -> Epp = spawn(fun() -> server(Self, Name, File, StartLocation,Path,Pdm) end), epp_request(Epp). --spec close(pid()) -> 'ok'. +-spec close(Epp) -> 'ok' when + Epp :: epp_handle(). close(Epp) -> %% Make sure that close is synchronous as a courtesy to test @@ -93,6 +104,13 @@ close(Epp) -> scan_erl_form(Epp) -> epp_request(Epp, scan_erl_form). +-spec parse_erl_form(Epp) -> + {'ok', AbsForm} | {'eof', Line} | {error, ErrorInfo} when + Epp :: epp_handle(), + AbsForm :: erl_parse:abstract_form(), + Line :: erl_scan:line(), + ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(). + parse_erl_form(Epp) -> case epp_request(Epp, scan_erl_form) of {ok,Toks} -> @@ -107,6 +125,9 @@ macro_defs(Epp) -> %% format_error(ErrorDescriptor) -> String %% Return a string describing the error. +-spec format_error(ErrorDescriptor) -> io_lib:chars() when + ErrorDescriptor :: term(). + format_error(cannot_parse) -> io_lib:format("cannot parse file, giving up", []); format_error({bad,W}) -> @@ -146,6 +167,16 @@ format_error(E) -> file:format_error(E). %% parse_file(FileName, IncludePath, [PreDefMacro]) -> %% {ok,[Form]} | {error,OpenError} +-spec parse_file(FileName, IncludePath, PredefMacros) -> + {'ok', [Form]} | {error, OpenError} when + FileName :: file:name(), + IncludePath :: [DirectoryName :: file:name()], + Form :: erl_parse:abstract_form() | {'error', ErrorInfo} | {'eof',Line}, + PredefMacros :: macros(), + Line :: erl_scan:line(), + ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(), + OpenError :: file:posix() | badarg | system_limit. + parse_file(Ifile, Path, Predefs) -> case open(Ifile, Path, Predefs) of {ok,Epp} -> @@ -653,7 +684,7 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}], {error,_E1} -> case catch find_lib_dir(NewName) of {LibDir, Rest} when is_list(LibDir) -> - LibName = filename:join([LibDir | Rest]), + LibName = fname_join([LibDir | Rest]), case file:open(LibName, [read]) of {ok,NewF} -> ExtraPath = [filename:dirname(LibName)], @@ -1123,7 +1154,12 @@ expand_var1(NewName) -> [[$$ | Var] | Rest] = filename:split(NewName), Value = os:getenv(Var), true = Value =/= false, - {ok, filename:join([Value | Rest])}. + {ok, fname_join([Value | Rest])}. + +fname_join(["." | [_|_]=Rest]) -> + fname_join(Rest); +fname_join(Components) -> + filename:join(Components). %% The line only. (Other tokens may have the column and text as well...) loc_attr(Line) when is_integer(Line) -> diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl index abff37e4bc..ff032b129c 100644 --- a/lib/stdlib/src/erl_compile.erl +++ b/lib/stdlib/src/erl_compile.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -41,7 +41,6 @@ compiler(".idl") -> {ic, compile}; compiler(".asn1") -> {asn1ct, compile_asn1}; compiler(".asn") -> {asn1ct, compile_asn}; compiler(".py") -> {asn1ct, compile_py}; -compiler(".xml") -> {xmerl_scan, process}; compiler(_) -> no. %% Entry from command line. diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index ea1b179ee5..4f4fa16040 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,6 +34,37 @@ -import(lists, [reverse/1,foldl/3,member/2]). +-export_type([binding_struct/0]). + +-type(expression() :: erl_parse:abstract_expr()). +-type(expressions() :: [erl_parse:abstract_expr()]). +-type(expression_list() :: [expression()]). +-type(clauses() :: [erl_parse:abstract_clause()]). +-type(name() :: term()). +-type(value() :: term()). +-type(bindings() :: [{name(), value()}]). +-type(binding_struct() :: orddict:orddict()). + +-type(lfun_value_handler() :: fun((Name :: atom(), + Arguments :: [term()]) -> + Value :: value())). +-type(lfun_eval_handler() :: fun((Name :: atom(), + Arguments :: expression_list(), + Bindings :: binding_struct()) -> + {value, + Value :: value(), + NewBindings :: binding_struct()})). +-type(local_function_handler() :: {value, lfun_value_handler()} + | {eval, lfun_eval_handler()} + | none). + +-type(func_spec() :: {Module :: module(), Function :: atom()} | function()). +-type(nlfun_handler() :: fun((FuncSpec :: func_spec(), + Arguments :: [term()]) -> + term())). +-type(non_local_function_handler() :: {value, nlfun_handler()} + | none). + %% exprs(ExpressionSeq, Bindings) %% exprs(ExpressionSeq, Bindings, LocalFuncHandler) %% exprs(ExpressionSeq, Bindings, LocalFuncHandler, ExternalFuncHandler) @@ -45,6 +76,11 @@ %% that there are valid constructs in Expression to be taken care of %% by a function handler but considerad errors by erl_lint. +-spec(exprs(Expressions, Bindings) -> {value, Value, NewBindings} when + Expressions :: expressions(), + Bindings :: binding_struct(), + Value :: value(), + NewBindings :: binding_struct()). exprs(Exprs, Bs) -> case check_command(Exprs, Bs) of ok -> @@ -53,9 +89,25 @@ exprs(Exprs, Bs) -> erlang:raise(error, Error, [{?MODULE,exprs,2}]) end. +-spec(exprs(Expressions, Bindings, LocalFunctionHandler) -> + {value, Value, NewBindings} when + Expressions :: expressions(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + Value :: value(), + NewBindings :: binding_struct()). exprs(Exprs, Bs, Lf) -> exprs(Exprs, Bs, Lf, none, none). +-spec(exprs(Expressions, Bindings, LocalFunctionHandler, + NonLocalFunctionHandler) -> + {value, Value, NewBindings} when + Expressions :: expressions(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + NonLocalFunctionHandler :: non_local_function_handler(), + Value :: value(), + NewBindings :: binding_struct()). exprs(Exprs, Bs, Lf, Ef) -> exprs(Exprs, Bs, Lf, Ef, none). @@ -75,6 +127,11 @@ exprs([E|Es], Bs0, Lf, Ef, RBs) -> %% %% Only expr/2 checks the command by calling erl_lint. See exprs/2. +-spec(expr(Expression, Bindings) -> {value, Value, NewBindings} when + Expression :: expression(), + Bindings :: binding_struct(), + Value :: value(), + NewBindings :: binding_struct()). expr(E, Bs) -> case check_command([E], Bs) of ok -> @@ -83,9 +140,25 @@ expr(E, Bs) -> erlang:raise(error, Error, [{?MODULE,expr,2}]) end. +-spec(expr(Expression, Bindings, LocalFunctionHandler) -> + {value, Value, NewBindings} when + Expression :: expression(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + Value :: value(), + NewBindings :: binding_struct()). expr(E, Bs, Lf) -> expr(E, Bs, Lf, none, none). +-spec(expr(Expression, Bindings, LocalFunctionHandler, + NonLocalFunctionHandler) -> + {value, Value, NewBindings} when + Expression :: expression(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + NonLocalFunctionHandler :: non_local_function_handler(), + Value :: value(), + NewBindings :: binding_struct()). expr(E, Bs, Lf, Ef) -> expr(E, Bs, Lf, Ef, none). @@ -114,6 +187,16 @@ fun_data(F) when is_function(F) -> fun_data(_T) -> false. +-spec(expr(Expression, Bindings, LocalFunctionHandler, + NonLocalFunctionHandler, ReturnFormat) -> + {value, Value, NewBindings} | Value when + Expression :: expression(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + NonLocalFunctionHandler :: non_local_function_handler(), + ReturnFormat :: none | value, + Value :: value(), + NewBindings :: binding_struct()). expr({var,_,V}, Bs, _Lf, _Ef, RBs) -> case binding(V, Bs) of {value,Val} -> @@ -384,12 +467,9 @@ local_func(Func, As0, Bs0, {value,F}, value) -> local_func(Func, As0, Bs0, {value,F}, RBs) -> {As1,Bs1} = expr_list(As0, Bs0, {value,F}), ret_expr(F(Func, As1), Bs1, RBs); -local_func(Func, As0, Bs0, {value,F,Eas}, value) -> - {As1,_Bs1} = expr_list(As0, Bs0, {value,F,Eas}), - apply(F, [Func,As1|Eas]); local_func(Func, As0, Bs0, {value,F,Eas}, RBs) -> - {As1,Bs1} = expr_list(As0, Bs0, {value,F,Eas}), - ret_expr(apply(F, [Func,As1|Eas]), Bs1, RBs); + Fun = fun(Name, Args) -> apply(F, [Name,Args|Eas]) end, + local_func(Func, As0, Bs0, {value, Fun}, RBs); local_func(Func, As, Bs, {eval,F}, RBs) -> local_func2(F(Func, As, Bs), RBs); local_func(Func, As, Bs, {eval,F,Eas}, RBs) -> @@ -541,7 +621,7 @@ eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) -> erlang:raise(error, {bad_generator,Term}, stacktrace()). eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) -> - Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end, + Mfun = match_fun(Bs0), Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end, case eval_bits:bin_gen(P, Bin, new_bindings(), Bs0, Mfun, Efun) of {match, Rest, Bs1} -> @@ -613,12 +693,33 @@ eval_fun([], As, _Bs, _Lf, _Ef, _RBs) -> %% expr_list(ExpressionList, Bindings, LocalFuncHandler, ExternalFuncHandler) %% Evaluate a list of expressions "in parallel" at the same level. +-spec(expr_list(ExpressionList, Bindings) -> {ValueList, NewBindings} when + ExpressionList :: expression_list(), + Bindings :: binding_struct(), + ValueList :: [value()], + NewBindings :: binding_struct()). expr_list(Es, Bs) -> expr_list(Es, Bs, none, none). +-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler) -> + {ValueList, NewBindings} when + ExpressionList :: expression_list(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + ValueList :: [value()], + NewBindings :: binding_struct()). expr_list(Es, Bs, Lf) -> expr_list(Es, Bs, Lf, none). +-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler, + NonLocalFunctionHandler) -> + {ValueList, NewBindings} when + ExpressionList :: expression_list(), + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + NonLocalFunctionHandler :: non_local_function_handler(), + ValueList :: [value()], + NewBindings :: binding_struct()). expr_list(Es, Bs, Lf, Ef) -> expr_list(Es, [], Bs, Bs, Lf, Ef). @@ -757,6 +858,15 @@ send_all([], _) -> true. %% match_clause -> {Body, Bindings} or nomatch +-spec(match_clause(Clauses, ValueList, Bindings, LocalFunctionHandler) -> + {Body, NewBindings} | nomatch when + Clauses :: clauses(), + ValueList :: [value()], + Bindings :: binding_struct(), + LocalFunctionHandler :: local_function_handler(), + Body :: expression_list(), + NewBindings :: binding_struct()). + match_clause(Cs, Vs, Bs, Lf) -> match_clause(Cs, Vs, Bs, Lf, none). @@ -914,7 +1024,7 @@ match1({tuple,_,_}, _, _Bs, _BBs) -> throw(nomatch); match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) -> eval_bits:match_bits(Fs, B, Bs0, BBs, - fun(L, R, Bs) -> match1(L, R, Bs, BBs) end, + match_fun(BBs), fun(E, Bs) -> expr(E, Bs, none, none, none) end); match1({bin,_,_}, _, _Bs, _BBs) -> throw(nomatch); @@ -943,6 +1053,12 @@ match1({op,Line,Op,L,R}, Term, Bs, BBs) -> match1(_, _, _Bs, _BBs) -> throw(invalid). +match_fun(BBs) -> + fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs); + (binding, {Name,Bs}) -> binding(Name, Bs); + (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs) + end. + match_tuple([E|Es], Tuple, I, Bs0, BBs) -> {match,Bs} = match1(E, element(I, Tuple), Bs0, BBs), match_tuple(Es, Tuple, I+1, Bs, BBs); @@ -973,18 +1089,30 @@ match_list(_, _, _Bs, _BBs) -> %% add_binding(Name, Value, Bindings) %% del_binding(Name, Bindings) +-spec(new_bindings() -> binding_struct()). new_bindings() -> orddict:new(). +-spec(bindings(BindingStruct :: binding_struct()) -> bindings()). bindings(Bs) -> orddict:to_list(Bs). +-spec(binding(Name, BindingStruct) -> {value, value()} | unbound when + Name :: name(), + BindingStruct :: binding_struct()). binding(Name, Bs) -> case orddict:find(Name, Bs) of {ok,Val} -> {value,Val}; error -> unbound end. +-spec(add_binding(Name, Value, BindingStruct) -> binding_struct() when + Name :: name(), + Value :: value(), + BindingStruct :: binding_struct()). add_binding(Name, Val, Bs) -> orddict:store(Name, Val, Bs). +-spec(del_binding(Name, BindingStruct) -> binding_struct() when + Name :: name(), + BindingStruct :: binding_struct()). del_binding(Name, Bs) -> orddict:erase(Name, Bs). add_bindings(Bs1, Bs2) -> diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 61ce41f714..20fd247cea 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -35,9 +35,13 @@ trecords=sets:new(), % Typed records uses_types=false, % Are there -spec or -type in the module strict_ra=[], % strict record accesses - checked_ra=[] % succesfully accessed records + checked_ra=[] % successfully accessed records }). +-spec(module(AbsForms, CompileOptions) -> AbsForms when + AbsForms :: [erl_parse:abstract_form()], + CompileOptions :: [compile:option()]). + %% Is is assumed that Fs is a valid list of forms. It should pass %% erl_lint without errors. module(Fs0, Opts0) -> diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl index b30b02a96f..cd3b531d10 100644 --- a/lib/stdlib/src/erl_internal.erl +++ b/lib/stdlib/src/erl_internal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,7 +54,9 @@ %%--------------------------------------------------------------------------- %% Erlang builtin functions allowed in guards. --spec guard_bif(Name::atom(), Arity::arity()) -> boolean(). +-spec guard_bif(Name, Arity) -> boolean() when + Name :: atom(), + Arity :: arity(). guard_bif(abs, 1) -> true; guard_bif(float, 1) -> true; @@ -92,7 +94,9 @@ guard_bif(binary_part, 3) -> true; guard_bif(Name, A) when is_atom(Name), is_integer(A) -> false. %% Erlang type tests. --spec type_test(Name::atom(), Arity::arity()) -> boolean(). +-spec type_test(Name, Arity) -> boolean() when + Name :: atom(), + Arity :: arity(). type_test(Name, Arity) -> new_type_test(Name, Arity) orelse old_type_test(Name, Arity). @@ -135,7 +139,9 @@ old_type_test(record, 2) -> true; old_type_test(function, 1) -> true; old_type_test(Name, A) when is_atom(Name), is_integer(A) -> false. --spec arith_op(Op::atom(), Arity::arity()) -> boolean(). +-spec arith_op(OpName, Arity) -> boolean() when + OpName :: atom(), + Arity :: arity(). arith_op('+', 1) -> true; arith_op('-', 1) -> true; @@ -153,7 +159,9 @@ arith_op('bsl', 2) -> true; arith_op('bsr', 2) -> true; arith_op(Op, A) when is_atom(Op), is_integer(A) -> false. --spec bool_op(Op::atom(), Arity::arity()) -> boolean(). +-spec bool_op(OpName, Arity) -> boolean() when + OpName :: atom(), + Arity :: arity(). bool_op('not', 1) -> true; bool_op('and', 2) -> true; @@ -161,7 +169,9 @@ bool_op('or', 2) -> true; bool_op('xor', 2) -> true; bool_op(Op, A) when is_atom(Op), is_integer(A) -> false. --spec comp_op(Op::atom(), Arity::arity()) -> boolean(). +-spec comp_op(OpName, Arity) -> boolean() when + OpName :: atom(), + Arity :: arity(). comp_op('==', 2) -> true; comp_op('/=', 2) -> true; @@ -173,18 +183,25 @@ comp_op('=:=', 2) -> true; comp_op('=/=', 2) -> true; comp_op(Op, A) when is_atom(Op), is_integer(A) -> false. --spec list_op(Op::atom(), Arity::arity()) -> boolean(). +-spec list_op(OpName, Arity) -> boolean() when + OpName :: atom(), + Arity :: arity(). list_op('++', 2) -> true; list_op('--', 2) -> true; list_op(Op, A) when is_atom(Op), is_integer(A) -> false. --spec send_op(Op::atom(), Arity::arity()) -> boolean(). +-spec send_op(OpName, Arity) -> boolean() when + OpName :: atom(), + Arity :: arity(). send_op('!', 2) -> true; send_op(Op, A) when is_atom(Op), is_integer(A) -> false. --spec op_type(atom(), arity()) -> 'arith' | 'bool' | 'comp' | 'list' | 'send'. +-spec op_type(OpName, Arity) -> Type when + OpName :: atom(), + Arity :: arity(), + Type :: 'arith' | 'bool' | 'comp' | 'list' | 'send'. op_type('+', 1) -> arith; op_type('-', 1) -> arith; @@ -221,7 +238,9 @@ op_type('!', 2) -> send. bif(erlang, Name, Arity) -> bif(Name, Arity); bif(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> false. --spec bif(Name::atom(), Arity::arity()) -> boolean(). +-spec bif(Name, Arity) -> boolean() when + Name :: atom(), + Arity::arity(). %% Returns true if erlang:Name/Arity is an auto-imported BIF, false otherwise. %% Use erlang:is_bultin(Mod, Name, Arity) to find whether a function is a BIF %% (meaning implemented in C) or not. @@ -243,8 +262,8 @@ bif(bitsize, 1) -> true; bif(bit_size, 1) -> true; bif(bitstring_to_list, 1) -> true; bif(byte_size, 1) -> true; +bif(check_old_code, 1) -> true; bif(check_process_code, 2) -> true; -bif(concat_binary, 1) -> true; bif(date, 0) -> true; bif(delete_module, 1) -> true; bif(demonitor, 1) -> true; @@ -386,7 +405,6 @@ old_bif(bit_size, 1) -> true; old_bif(bitstring_to_list, 1) -> true; old_bif(byte_size, 1) -> true; old_bif(check_process_code, 2) -> true; -old_bif(concat_binary, 1) -> true; old_bif(date, 0) -> true; old_bif(delete_module, 1) -> true; old_bif(disconnect_node, 1) -> true; diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index cfb9f0ca98..78b996d94b 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -123,15 +123,21 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> called= [] :: [{fa(),line()}], %Called functions usage = #usage{} :: #usage{}, specs = dict:new() :: dict(), %Type specifications + callbacks = dict:new() :: dict(), %Callback types types = dict:new() :: dict(), %Type definitions exp_types=gb_sets:empty():: gb_set() %Exported types }). -type lint_state() :: #lint{}. +-type error_description() :: term(). +-type error_info() :: {erl_scan:line(), module(), error_description()}. %% format_error(Error) %% Return a string describing the error. +-spec format_error(ErrorDescriptor) -> io_lib:chars() when + ErrorDescriptor :: error_description(). + format_error(undefined_module) -> "no module definition"; format_error({bad_module_name, M}) -> @@ -305,8 +311,6 @@ format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) -> format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}) -> io_lib:format("undefined callback function ~w/~w (behaviour '~w')", [Func,Arity,Behaviour]); -format_error({undefined_behaviour_func, {Func,Arity,_Spec}, Behaviour}) -> - format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}); format_error({undefined_behaviour,Behaviour}) -> io_lib:format("behaviour ~w undefined", [Behaviour]); format_error({undefined_behaviour_callbacks,Behaviour}) -> @@ -315,6 +319,9 @@ format_error({undefined_behaviour_callbacks,Behaviour}) -> format_error({ill_defined_behaviour_callbacks,Behaviour}) -> io_lib:format("behaviour ~w callback functions erroneously defined", [Behaviour]); +format_error({behaviour_info, {_M,F,A}}) -> + io_lib:format("cannot define callback attibute for ~w/~w when " + "behaviour_info is defined",[F,A]); %% --- types and specs --- format_error({singleton_typevar, Name}) -> io_lib:format("type variable ~w is only used once (is unbound)", [Name]); @@ -343,12 +350,16 @@ format_error({type_syntax, Constr}) -> io_lib:format("bad ~w type", [Constr]); format_error({redefine_spec, {M, F, A}}) -> io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]); +format_error({redefine_callback, {M, F, A}}) -> + io_lib:format("callback ~w:~w/~w already defined", [M, F, A]); format_error({spec_fun_undefined, {M, F, A}}) -> io_lib:format("spec for undefined function ~w:~w/~w", [M, F, A]); format_error({missing_spec, {F,A}}) -> io_lib:format("missing specification for function ~w/~w", [F, A]); format_error(spec_wrong_arity) -> "spec has the wrong arity"; +format_error(callback_wrong_arity) -> + "callback has the wrong arity"; format_error({imported_predefined_type, Name}) -> io_lib:format("referring to built-in type ~w as a remote type; " "please take out the module name", [Name]); @@ -419,16 +430,39 @@ used_vars(Exprs, BindingsList) -> %% apply_lambda/2 has been called to shut lint up. N.B. these lists are %% really all ordsets! +-spec(module(AbsForms) -> {ok, Warnings} | {error, Errors, Warnings} when + AbsForms :: [erl_parse:abstract_form()], + Warnings :: [{file:filename(),[ErrorInfo]}], + Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], + ErrorInfo :: error_info()). + module(Forms) -> Opts = compiler_options(Forms), St = forms(Forms, start("nofile", Opts)), return_status(St). +-spec(module(AbsForms, FileName) -> + {ok, Warnings} | {error, Errors, Warnings} when + AbsForms :: [erl_parse:abstract_form()], + FileName :: atom() | string(), + Warnings :: [{file:filename(),[ErrorInfo]}], + Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], + ErrorInfo :: error_info()). + module(Forms, FileName) -> Opts = compiler_options(Forms), St = forms(Forms, start(FileName, Opts)), return_status(St). +-spec(module(AbsForms, FileName, CompileOptions) -> + {ok, Warnings} | {error, Errors, Warnings} when + AbsForms :: [erl_parse:abstract_form()], + FileName :: atom() | string(), + CompileOptions :: [compile:option()], + Warnings :: [{file:filename(),[ErrorInfo]}], + Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], + ErrorInfo :: error_info()). + module(Forms, FileName, Opts0) -> %% We want the options given on the command line to take %% precedence over options in the module. @@ -719,6 +753,8 @@ attribute_state({attribute,L,opaque,{TypeName,TypeDef,Args}}, St) -> type_def(opaque, L, TypeName, TypeDef, Args, St); attribute_state({attribute,L,spec,{Fun,Types}}, St) -> spec_decl(L, Fun, Types, St); +attribute_state({attribute,L,callback,{Fun,Types}}, St) -> + callback_decl(L, Fun, Types, St); attribute_state({attribute,L,on_load,Val}, St) -> on_load(L, Val, St); attribute_state({attribute,_L,_Other,_Val}, St) -> % Ignore others @@ -812,7 +848,8 @@ post_traversal_check(Forms, St0) -> StB = check_unused_types(Forms, StA), StC = check_untyped_records(Forms, StB), StD = check_on_load(StC), - check_unused_records(Forms, StD). + StE = check_unused_records(Forms, StD), + check_callback_information(StE). %% check_behaviour(State0) -> State %% Check that the behaviour attribute is valid. @@ -1111,6 +1148,23 @@ check_unused_records(Forms, St0) -> St0 end. +check_callback_information(#lint{callbacks = Callbacks, + defined = Defined} = State) -> + case gb_sets:is_member({behaviour_info,1}, Defined) of + false -> State; + true -> + case dict:size(Callbacks) of + 0 -> State; + _ -> + CallbacksList = dict:to_list(Callbacks), + FoldL = + fun({Fa,Line},St) -> + add_error(Line, {behaviour_info, Fa}, St) + end, + lists:foldl(FoldL, State, CallbacksList) + end + end. + %% For storing the import list we use the orddict module. %% We know an empty set is []. @@ -1877,6 +1931,9 @@ gexpr_list(Es, Vt, St) -> %% is_guard_test(Expression) -> boolean(). %% Test if a general expression is a guard test. +-spec is_guard_test(Expr) -> boolean() when + Expr :: erl_parse:abstract_expr(). + is_guard_test(E) -> is_guard_test2(E, dict:new()). @@ -2739,6 +2796,20 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> false -> check_specs(TypeSpecs, Arity, St1) end. +%% callback_decl(Line, Fun, Types, State) -> State. + +callback_decl(Line, MFA0, TypeSpecs, + St0 = #lint{callbacks = Callbacks, module = Mod}) -> + MFA = case MFA0 of + {F, Arity} -> {Mod, F, Arity}; + {_M, _F, Arity} -> MFA0 + end, + St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)}, + case dict:is_key(MFA, Callbacks) of + true -> add_error(Line, {redefine_callback, MFA}, St1); + false -> check_specs(TypeSpecs, Arity, St1) + end. + check_specs([FunType|Left], Arity, St0) -> {FunType1, CTypes} = case FunType of @@ -3244,6 +3315,8 @@ modify_line1({attribute,L,record,{Name,Fields}}, Mf) -> {attribute,Mf(L),record,{Name,modify_line1(Fields, Mf)}}; modify_line1({attribute,L,spec,{Fun,Types}}, Mf) -> {attribute,Mf(L),spec,{Fun,modify_line1(Types, Mf)}}; +modify_line1({attribute,L,callback,{Fun,Types}}, Mf) -> + {attribute,Mf(L),callback,{Fun,modify_line1(Types, Mf)}}; modify_line1({attribute,L,type,{TypeName,TypeDef,Args}}, Mf) -> {attribute,Mf(L),type,{TypeName,modify_line1(TypeDef, Mf), modify_line1(Args, Mf)}}; diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 15b45d72f4..709bd83e6f 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -62,7 +62,7 @@ char integer float atom string var '==' '/=' '=<' '<' '>=' '>' '=:=' '=/=' '<=' '<<' '>>' '!' '=' '::' '..' '...' -'spec' % helper +'spec' 'callback' % helper dot. Expect 2. @@ -77,6 +77,7 @@ attribute -> '-' atom attr_val : build_attribute('$2', '$3'). attribute -> '-' atom typed_attr_val : build_typed_attribute('$2','$3'). attribute -> '-' atom '(' typed_attr_val ')' : build_typed_attribute('$2','$4'). attribute -> '-' 'spec' type_spec : build_type_spec('$2', '$3'). +attribute -> '-' 'callback' type_spec : build_type_spec('$2', '$3'). type_spec -> spec_fun type_sigs : {'$1', '$2'}. type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}. @@ -511,6 +512,15 @@ Erlang code. %% of the generated .erl file by the HiPE compiler. Please do not remove. -compile([{hipe,[{regalloc,linear_scan}]}]). +-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0, + error_info/0]). + +-type abstract_clause() :: term(). +-type abstract_expr() :: term(). +-type abstract_form() :: term(). +-type error_description() :: term(). +-type error_info() :: {erl_scan:line(), module(), error_description()}. +-type token() :: {Tag :: atom(), Line :: erl_scan:line()}. %% mkop(Op, Arg) -> {op,Line,Op,Arg}. %% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}. @@ -534,11 +544,21 @@ Erlang code. %% These really suck and are only here until Calle gets multiple %% entry points working. +-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when + Tokens :: [token()], + AbsForm :: abstract_form(), + ErrorInfo :: error_info(). parse_form([{'-',L1},{atom,L2,spec}|Tokens]) -> parse([{'-',L1},{'spec',L2}|Tokens]); +parse_form([{'-',L1},{atom,L2,callback}|Tokens]) -> + parse([{'-',L1},{'callback',L2}|Tokens]); parse_form(Tokens) -> parse(Tokens). +-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when + Tokens :: [token()], + ExprList :: [abstract_expr()], + ErrorInfo :: error_info(). parse_exprs(Tokens) -> case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} -> @@ -546,6 +566,10 @@ parse_exprs(Tokens) -> {error,_} = Err -> Err end. +-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when + Tokens :: [token()], + Term :: term(), + ErrorInfo :: error_info(). parse_term(Tokens) -> case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} -> @@ -582,7 +606,8 @@ build_typed_attribute({atom,La,Attr},_) -> _ -> ret_err(La, "bad attribute") end. -build_type_spec({spec,La}, {SpecFun, TypeSpecs}) -> +build_type_spec({Kind,La}, {SpecFun, TypeSpecs}) + when (Kind =:= spec) or (Kind =:= callback) -> NewSpecFun = case SpecFun of {atom, _, Fun} -> @@ -596,7 +621,7 @@ build_type_spec({spec,La}, {SpecFun, TypeSpecs}) -> %% Old style spec. Allow this for now. {Mod,Fun,Arity} end, - {attribute,La,spec,{NewSpecFun, TypeSpecs}}. + {attribute,La,Kind,{NewSpecFun, TypeSpecs}}. find_arity_from_specs([Spec|_]) -> %% Use the first spec to find the arity. If all are not the same, @@ -830,6 +855,7 @@ check_clauses(Cs, Name, Arity) -> build_try(L,Es,Scs,{Ccs,As}) -> {'try',L,Es,Scs,Ccs,As}. +-spec ret_err(_, _) -> no_return(). ret_err(L, S) -> {location,Location} = get_attribute(L, location), return_error(Location, S). @@ -846,10 +872,11 @@ mapl(F, [H|T]) -> mapl(_, []) -> []. -%% normalise(AbsTerm) -%% abstract(Term) %% Convert between the abstract form of a term and a term. +-spec normalise(AbsTerm) -> Data when + AbsTerm :: abstract_expr(), + Data :: term(). normalise({char,_,C}) -> C; normalise({integer,_,I}) -> I; normalise({float,_,F}) -> F; @@ -887,6 +914,9 @@ normalise_list([H|T]) -> normalise_list([]) -> []. +-spec abstract(Data) -> AbsTerm when + Data :: term(), + AbsTerm :: abstract_expr(). abstract(T) when is_integer(T) -> {integer,0,T}; abstract(T) when is_float(T) -> {float,0,T}; abstract(T) when is_atom(T) -> {atom,0,T}; @@ -955,13 +985,18 @@ abstract_list([H|T], Line) -> abstract_list([], _Line) -> []. -%% tokens(AbsTerm) -> [Token] -%% tokens(AbsTerm, More) -> [Token] %% Generate a list of tokens representing the abstract term. +-spec tokens(AbsTerm) -> Tokens when + AbsTerm :: abstract_expr(), + Tokens :: [token()]. tokens(Abs) -> tokens(Abs, []). +-spec tokens(AbsTerm, MoreTokens) -> Tokens when + AbsTerm :: abstract_expr(), + MoreTokens :: [token()], + Tokens :: [token()]. tokens({char,L,C}, More) -> [{char,L,C}|More]; tokens({integer,L,N}, More) -> [{integer,L,N}|More]; tokens({float,L,F}, More) -> [{float,L,F}|More]; diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 66c80a45cb..7dc19f2e9b 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -31,25 +31,53 @@ -define(MAXLINE, 72). +-type(hook_function() :: none + | fun((Expr :: erl_parse:abstract_expr(), + CurrentIndentation :: integer(), + CurrentPrecedence :: non_neg_integer(), + HookFunction :: hook_function()) -> + io_lib:chars())). + %%% %%% Exported functions %%% +-spec(form(Form) -> io_lib:chars() when + Form :: erl_parse:abstract_form()). + form(Thing) -> form(Thing, none). +-spec(form(Form, HookFunction) -> io_lib:chars() when + Form :: erl_parse:abstract_form(), + HookFunction :: hook_function()). + form(Thing, Hook) -> frmt(lform(Thing, Hook)). +-spec(attribute(Attribute) -> io_lib:chars() when + Attribute :: erl_parse:abstract_form()). + attribute(Thing) -> attribute(Thing, none). +-spec(attribute(Attribute, HookFunction) -> io_lib:chars() when + Attribute :: erl_parse:abstract_form(), + HookFunction :: hook_function()). + attribute(Thing, Hook) -> frmt(lattribute(Thing, Hook)). +-spec(function(Function) -> io_lib:chars() when + Function :: erl_parse:abstract_form()). + function(F) -> function(F, none). +-spec(function(Function, HookFunction) -> io_lib:chars() when + Function :: erl_parse:abstract_form(), + HookFunction :: hook_function()). + function(F, Hook) -> frmt(lfunction(F, Hook)). @@ -59,30 +87,67 @@ rule(R) -> rule(R, Hook) -> frmt(lrule(R, Hook)). +-spec(guard(Guard) -> io_lib:chars() when + Guard :: [erl_parse:abstract_expr()]). + guard(Gs) -> guard(Gs, none). +-spec(guard(Guard, HookFunction) -> io_lib:chars() when + Guard :: [erl_parse:abstract_expr()], + HookFunction :: hook_function()). + guard(Gs, Hook) -> frmt(lguard(Gs, Hook)). +-spec(exprs(Expressions) -> io_lib:chars() when + Expressions :: [erl_parse:abstract_expr()]). + exprs(Es) -> exprs(Es, 0, none). +-spec(exprs(Expressions, HookFunction) -> io_lib:chars() when + Expressions :: [erl_parse:abstract_expr()], + HookFunction :: hook_function()). + exprs(Es, Hook) -> exprs(Es, 0, Hook). +-spec(exprs(Expressions, Indent, HookFunction) -> io_lib:chars() when + Expressions :: [erl_parse:abstract_expr()], + Indent :: integer(), + HookFunction :: hook_function()). + exprs(Es, I, Hook) -> frmt({seq,[],[],[$,],lexprs(Es, Hook)}, I). +-spec(expr(Expression) -> io_lib:chars() when + Expression :: erl_parse:abstract_expr()). + expr(E) -> frmt(lexpr(E, 0, none)). +-spec(expr(Expression, HookFunction) -> io_lib:chars() when + Expression :: erl_parse:abstract_expr(), + HookFunction :: hook_function()). + expr(E, Hook) -> frmt(lexpr(E, 0, Hook)). +-spec(expr(Expression, Indent, HookFunction) -> io_lib:chars() when + Expression :: erl_parse:abstract_expr(), + Indent :: integer(), + HookFunction :: hook_function()). + expr(E, I, Hook) -> frmt(lexpr(E, 0, Hook), I). +-spec(expr(Expression, Indent, Precedence, HookFunction) -> io_lib:chars() when + Expression :: erl_parse:abstract_expr(), + Indent :: integer(), + Precedence :: non_neg_integer(), + HookFunction :: hook_function()). + expr(E, I, P, Hook) -> frmt(lexpr(E, P, Hook), I). diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index 18f64c46d0..10b2ed2e49 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -99,7 +99,8 @@ %%---------------------------------------------------------------------------- --spec format_error(Error :: term()) -> string(). +-spec format_error(ErrorDescriptor) -> string() when + ErrorDescriptor :: error_description(). format_error({string,Quote,Head}) -> lists:flatten(["unterminated " ++ string_thing(Quote) ++ " starting with " ++ @@ -112,20 +113,33 @@ format_error({base,Base}) -> format_error(Other) -> lists:flatten(io_lib:write(Other)). --type string_return() :: {'ok', tokens(), location()} - | {'error', error_info(), location()}. - --spec string(String :: string()) -> string_return(). +-spec string(String) -> Return when + String :: string(), + Return :: {'ok', Tokens :: tokens(), EndLocation} + | {'error', ErrorInfo :: error_info(), ErrorLocation}, + EndLocation :: location(), + ErrorLocation :: location(). string(String) -> string(String, 1, []). --spec string(String :: string(), StartLocation :: location()) -> - string_return(). +-spec string(String, StartLocation) -> Return when + String :: string(), + Return :: {'ok', Tokens :: tokens(), EndLocation} + | {'error', ErrorInfo :: error_info(), ErrorLocation}, + StartLocation :: location(), + EndLocation :: location(), + ErrorLocation :: location(). string(String, StartLocation) -> string(String, StartLocation, []). --spec string(String :: string(), StartLocation :: location(), - Options :: options()) -> string_return(). +-spec string(String, StartLocation, Options) -> Return when + String :: string(), + Options :: options(), + Return :: {'ok', Tokens :: tokens(), EndLocation} + | {'error', ErrorInfo :: error_info(), ErrorLocation}, + StartLocation :: location(), + EndLocation :: location(), + ErrorLocation :: location(). string(String, Line, Options) when ?STRING(String), ?ALINE(Line) -> string1(String, options(Options), Line, no_col, []); string(String, {Line,Column}, Options) when ?STRING(String), @@ -136,29 +150,37 @@ string(String, {Line,Column}, Options) when ?STRING(String), -type char_spec() :: string() | 'eof'. -type cont_fun() :: fun((char_spec(), #erl_scan{}, line(), column(), tokens(), any()) -> any()). --opaque return_cont() :: {string(), column(), tokens(), line(), - #erl_scan{}, cont_fun(), any()}. --type cont() :: return_cont() | []. --type tokens_result() :: {'ok', tokens(), location()} - | {'eof', location()} - | {'error', error_info(), location()}. --type tokens_return() :: {'done', tokens_result(), char_spec()} - | {'more', return_cont()}. - --spec tokens(Cont :: cont(), CharSpec :: char_spec(), - StartLocation :: location()) -> tokens_return(). +-opaque return_cont() :: {erl_scan_continuation, + string(), column(), tokens(), line(), + #erl_scan{}, any(), cont_fun()}. +-type tokens_result() :: {'ok', Tokens :: tokens(), EndLocation :: location()} + | {'eof', EndLocation :: location()} + | {'error', ErrorInfo :: error_info(), + EndLocation :: location()}. + +-spec tokens(Continuation, CharSpec, StartLocation) -> Return when + Continuation :: return_cont() | [], + CharSpec :: char_spec(), + StartLocation :: location(), + Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} + | {'more', Continuation1 :: return_cont()}. tokens(Cont, CharSpec, StartLocation) -> tokens(Cont, CharSpec, StartLocation, []). --spec tokens(Cont :: cont(), CharSpec :: char_spec(), - StartLocation :: location(), Options :: options()) -> - tokens_return(). +-spec tokens(Continuation, CharSpec, StartLocation, Options) -> Return when + Continuation :: return_cont() | [], + CharSpec :: char_spec(), + StartLocation :: location(), + Options :: options(), + Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()} + | {'more', Continuation1 :: return_cont()}. tokens([], CharSpec, Line, Options) when ?ALINE(Line) -> tokens1(CharSpec, options(Options), Line, no_col, [], fun scan/6, []); tokens([], CharSpec, {Line,Column}, Options) when ?ALINE(Line), ?COLUMN(Column) -> tokens1(CharSpec, options(Options), Line, Column, [], fun scan/6, []); -tokens({Cs,Col,Toks,Line,St,Any,Fun}, CharSpec, _Loc, _Opts) -> +tokens({erl_scan_continuation,Cs,Col,Toks,Line,St,Any,Fun}, + CharSpec, _Loc, _Opts) -> tokens1(Cs++CharSpec, St, Line, Col, Toks, Fun, Any). -type attribute_item() :: 'column' | 'length' | 'line' @@ -172,13 +194,22 @@ tokens({Cs,Col,Toks,Line,St,Any,Fun}, CharSpec, _Loc, _Opts) -> -type token_info() :: {'category', category()} | {'symbol', symbol()} | attribute_info(). --spec token_info(token()) -> [token_info()]. +-spec token_info(Token) -> TokenInfo when + Token :: token(), + TokenInfo :: [TokenInfoTuple :: token_info()]. token_info(Token) -> Items = [category,column,length,line,symbol,text], % undefined order token_info(Token, Items). --spec token_info(token(), token_item()) -> token_info() | 'undefined'; - (token(), [token_item()]) -> [token_info()]. +-spec token_info(Token, TokenItem) -> TokenInfo | 'undefined' when + Token :: token(), + TokenItem :: token_item(), + TokenInfo :: TokenInfoTuple :: token_info(); + (Token, TokenItems) -> [TokenInfo] when + Token :: token(), + TokenItems :: [TokenItem], + TokenItem :: token_item(), + TokenInfo :: [TokenInfoTuple :: token_info()]. token_info(_Token, []) -> []; token_info(Token, [Item|Items]) when is_atom(Item) -> @@ -201,14 +232,23 @@ token_info({_Category,Attrs}, Item) -> token_info({_Category,Attrs,_Symbol}, Item) -> attributes_info(Attrs, Item). --spec attributes_info(attributes()) -> [attribute_info()]. +-spec attributes_info(Attributes) -> AttributesInfo when + Attributes :: attributes(), + AttributesInfo :: [AttributeInfoTuple :: attribute_info()]. attributes_info(Attributes) -> Items = [column,length,line,text], % undefined order attributes_info(Attributes, Items). --spec attributes_info(attributes(), attribute_item()) -> - attribute_info() | 'undefined'; - (attributes(), [attribute_item()]) -> [attribute_info()]. +-spec attributes_info(Attributes, AttributeItem) -> + AttributeInfo | 'undefined' when + Attributes :: attributes(), + AttributeItem :: attribute_item(), + AttributeInfo :: AttributeInfoTuple :: attribute_info(); + (Attributes, AttributeItems) -> [AttributeInfo] when + Attributes :: attributes(), + AttributeItems :: [AttributeItem], + AttributeItem :: attribute_item(), + AttributeInfo :: [AttributeInfoTuple :: attribute_info()]. attributes_info(_Attrs, []) -> []; attributes_info(Attrs, [A|As]) when is_atom(A) -> @@ -265,9 +305,10 @@ attributes_info(Attrs, text=Item) -> attributes_info(T1, T2) -> erlang:error(badarg, [T1,T2]). --type setlineattr_fun() :: fun((info_line()) -> info_line()). - --spec set_attribute('line', attributes(), setlineattr_fun()) -> attributes(). +-spec set_attribute(AttributeItem, Attributes, SetAttributeFun) -> Attributes when + AttributeItem :: 'line', + Attributes :: attributes(), + SetAttributeFun :: fun((info_line()) -> info_line()). set_attribute(Tag, Attributes, Fun) when ?SETATTRFUN(Fun) -> set_attr(Tag, Attributes, Fun). @@ -367,14 +408,19 @@ set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) -> end; set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) -> {line,Line} = lists:keyfind(Tag, 1, Attrs), - lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}); + case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of + [{line,Ln}] when ?ALINE(Ln) -> + Ln; + As -> + As + end; set_attr(T1, T2, T3) -> erlang:error(badarg, [T1,T2,T3]). tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof -> case Fun(Cs, St, Line, Col, Toks, Any) of {more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} -> - {more,{Cs0,Ncol,Ntoks,Nline,St,Nany,Nfun}}; + {more,{erl_scan_continuation,Cs0,Ncol,Ntoks,Nline,St,Nany,Nfun}}; {ok,Toks0,eof,Nline,Ncol} -> Res = case Toks0 of [] -> @@ -1285,7 +1331,7 @@ tabs(8) -> "\t\t\t\t\t\t\t\t"; tabs(9) -> "\t\t\t\t\t\t\t\t\t"; tabs(10) -> "\t\t\t\t\t\t\t\t\t\t". --spec reserved_word(atom()) -> boolean(). +-spec reserved_word(Atom :: atom()) -> boolean(). reserved_word('after') -> true; reserved_word('begin') -> true; reserved_word('case') -> true; diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl index fd85c7aef5..306834e845 100644 --- a/lib/stdlib/src/erl_tar.erl +++ b/lib/stdlib/src/erl_tar.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -798,30 +798,10 @@ set_extracted_file_info(Name, #tar_header{mode=Mode, mtime=Mtime}) -> %% Makes all directories leading up to the file. -make_dirs(Name, Type) -> - make_dirs1(filename:split(Name), Type). - -make_dirs1([Dir, Next|Rest], Type) -> - case file:read_file_info(Dir) of - {ok, #file_info{type=directory}} -> - make_dirs1([filename:join(Dir, Next)|Rest], Type); - {ok, #file_info{}} -> - throw({error, enotdir}); - {error, _} -> - case file:make_dir(Dir) of - ok -> - make_dirs1([filename:join(Dir, Next)|Rest], Type); - {error, Reason} -> - throw({error, Reason}) - end - end; -make_dirs1([_], file) -> ok; -make_dirs1([Dir], dir) -> - file:make_dir(Dir); -make_dirs1([], _) -> - %% There must be something wrong here. The list was not supposed - %% to be empty. - throw({error, enoent}). +make_dirs(Name, file) -> + filelib:ensure_dir(Name); +make_dirs(Name, dir) -> + filelib:ensure_dir(filename:join(Name,"*")). %% Prints the message on if the verbose option is given (for reading). diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl index 435e57aa0e..fa13fbb2bd 100644 --- a/lib/stdlib/src/error_logger_tty_h.erl +++ b/lib/stdlib/src/error_logger_tty_h.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,10 +34,12 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). +-export([write_event/2]). + %% This one is used when we takeover from the simple error_logger. init({[], {error_logger, Buf}}) -> User = set_group_leader(), - write_events(Buf), + write_events(Buf,io), {ok, {User, error_logger}}; %% This one is used if someone took over from us, and now wants to %% go back. @@ -52,7 +54,7 @@ init([]) -> handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() -> {ok, State}; handle_event(Event, State) -> - write_event(tag_event(Event)), + write_event(tag_event(Event),io), {ok, State}. handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) -> @@ -64,10 +66,10 @@ handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) -> PrevHandler, go_back} end; handle_info({emulator, GL, Chars}, State) when node(GL) == node() -> - write_event(tag_event({emulator, GL, Chars})), + write_event(tag_event({emulator, GL, Chars}),io), {ok, State}; handle_info({emulator, noproc, Chars}, State) -> - write_event(tag_event({emulator, noproc, Chars})), + write_event(tag_event({emulator, noproc, Chars}),io), {ok, State}; handle_info(_, State) -> {ok, State}. @@ -97,65 +99,65 @@ set_group_leader() -> tag_event(Event) -> {erlang:localtime(), Event}. -write_events(Events) -> write_events1(lists:reverse(Events)). +write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod). -write_events1([Event|Es]) -> - write_event(Event), - write_events1(Es); -write_events1([]) -> +write_events1([Event|Es],IOMod) -> + write_event(Event,IOMod), + write_events1(Es,IOMod); +write_events1([],_IOMod) -> ok. -write_event({Time, {error, _GL, {Pid, Format, Args}}}) -> +write_event({Time, {error, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time)), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({Time, {emulator, _GL, Chars}}) -> +write_event({Time, {emulator, _GL, Chars}},IOMod) -> T = write_time(maybe_utc(Time)), case catch io_lib:format(Chars, []) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> - format(T ++ "ERROR: ~p ~n", [Chars]) + format(IOMod, T ++ "ERROR: ~p ~n", [Chars]) end; -write_event({Time, {info, _GL, {Pid, Info, _}}}) -> +write_event({Time, {info, _GL, {Pid, Info, _}}},IOMod) -> T = write_time(maybe_utc(Time)), - format(T ++ add_node("~p~n",Pid),[Info]); -write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}}) -> + format(IOMod, T ++ add_node("~p~n",Pid),[Info]); +write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}},IOMod) -> T = write_time(maybe_utc(Time)), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}},IOMod) -> T = write_time(maybe_utc(Time), "INFO REPORT"), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {info_msg, _GL, {Pid, Format, Args}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {info_msg, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time), "INFO REPORT"), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}}) -> +write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}},IOMod) -> T = write_time(maybe_utc(Time), "WARNING REPORT"), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time), "WARNING REPORT"), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({_Time, _Error}) -> +write_event({_Time, _Error},_IOMod) -> ok. maybe_utc(Time) -> @@ -178,8 +180,9 @@ maybe_utc(Time) -> Time end. -format(String) -> io:format(user, String, []). -format(String, Args) -> io:format(user, String, Args). +format(IOMod, String) -> format(IOMod, String, []). +format(io_lib, String, Args) -> io_lib:format(String, Args); +format(io, String, Args) -> io:format(user, String, Args). format_report(Rep) when is_list(Rep) -> case string_p(Rep) of diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index d67617260e..ad49d89908 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -62,10 +62,10 @@ -type zip_create_option() :: term(). -type section() :: shebang - | {shebang, shebang()} + | {shebang, shebang() | default | undefined} | comment - | {comment, comment()} - | {emu_args, emu_args()} + | {comment, comment() | default | undefined} + | {emu_args, emu_args() | undefined} | {source, file:filename() | binary()} | {beam, file:filename() | binary()} | {archive, file:filename() | binary()} @@ -866,7 +866,7 @@ hidden_apply(App, M, F, Args) -> catch error:undef -> case erlang:get_stacktrace() of - [{M,F,Args} | _] -> + [{M,F,Args,_} | _] -> Arity = length(Args), Text = io_lib:format("Call to ~w:~w/~w in application ~w failed.\n", [M, F, Arity, App]), diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index 6e6e949e2c..afa914a456 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -42,7 +42,7 @@ -export([i/0, i/1, i/2, i/3]). --export_type([tab/0, tid/0]). +-export_type([tab/0, tid/0, match_spec/0]). %%----------------------------------------------------------------------------- @@ -51,22 +51,9 @@ %% a similar definition is also in erl_types -opaque tid() :: integer(). --type ext_info() :: 'md5sum' | 'object_count'. --type protection() :: 'private' | 'protected' | 'public'. --type type() :: 'bag' | 'duplicate_bag' | 'ordered_set' | 'set'. - --type table_info() :: {'name', atom()} - | {'type', type()} - | {'protection', protection()} - | {'named_table', boolean()} - | {'keypos', non_neg_integer()} - | {'size', non_neg_integer()} - | {'extended_info', [ext_info()]} - | {'version', {non_neg_integer(), non_neg_integer()}}. - %% these ones are also defined in erl_bif_types -type match_pattern() :: atom() | tuple(). --type match_specs() :: [{match_pattern(), [_], [_]}]. +-type match_spec() :: [{match_pattern(), [_], [_]}]. %%----------------------------------------------------------------------------- @@ -86,6 +73,7 @@ %% insert/2 %% is_compiled_ms/1 %% last/1 +%% member/2 %% next/2 %% prev/2 %% rename/2 @@ -101,11 +89,14 @@ %% select/1 %% select/2 %% select/3 +%% select_count/2 %% select_reverse/1 %% select_reverse/2 %% select_reverse/3 %% select_delete/2 +%% setopts/2 %% update_counter/3 +%% update_element/3 %% -opaque comp_match_spec() :: any(). %% this one is REALLY opaque @@ -119,7 +110,9 @@ match_spec_run(List, CompiledMS) -> | {tab(),integer(),integer(),binary(),list(),integer()} | {tab(),_,_,integer(),binary(),list(),integer(),integer()}. --spec repair_continuation(continuation(), match_specs()) -> continuation(). +-spec repair_continuation(Continuation, MatchSpec) -> Continuation when + Continuation :: continuation(), + MatchSpec :: match_spec(). %% $end_of_table is an allowed continuation in ets... repair_continuation('$end_of_table', _) -> @@ -153,7 +146,9 @@ repair_continuation(Untouched = {Table,N1,N2,Bin,L,N3}, MS) {Table,N1,N2,ets:match_spec_compile(MS),L,N3} end. --spec fun2ms(function()) -> match_specs(). +-spec fun2ms(LiteralFun) -> MatchSpec when + LiteralFun :: function(), + MatchSpec :: match_spec(). fun2ms(ShellFun) when is_function(ShellFun) -> %% Check that this is really a shell fun... @@ -177,7 +172,13 @@ fun2ms(ShellFun) when is_function(ShellFun) -> shell]}}) end. --spec foldl(fun((_, term()) -> term()), term(), tab()) -> term(). +-spec foldl(Function, Acc0, Tab) -> Acc1 when + Function :: fun((Element :: term(), AccIn) -> AccOut), + Tab :: tab(), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(). foldl(F, Accu, T) -> ets:safe_fixtable(T, true), @@ -198,7 +199,13 @@ do_foldl(F, Accu0, Key, T) -> ets:next(T, Key), T) end. --spec foldr(fun((_, term()) -> term()), term(), tab()) -> term(). +-spec foldr(Function, Acc0, Tab) -> Acc1 when + Function :: fun((Element :: term(), AccIn) -> AccOut), + Tab :: tab(), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(). foldr(F, Accu, T) -> ets:safe_fixtable(T, true), @@ -219,7 +226,9 @@ do_foldr(F, Accu0, Key, T) -> ets:prev(T, Key), T) end. --spec from_dets(tab(), dets:tab_name()) -> 'true'. +-spec from_dets(Tab, DetsTab) -> 'true' when + Tab :: tab(), + DetsTab :: dets:tab_name(). from_dets(EtsTable, DetsTable) -> case (catch dets:to_ets(DetsTable, EtsTable)) of @@ -235,7 +244,9 @@ from_dets(EtsTable, DetsTable) -> erlang:error(Unexpected,[EtsTable,DetsTable]) end. --spec to_dets(tab(), dets:tab_name()) -> dets:tab_name(). +-spec to_dets(Tab, DetsTab) -> DetsTab when + Tab :: tab(), + DetsTab :: dets:tab_name(). to_dets(EtsTable, DetsTable) -> case (catch dets:from_ets(DetsTable, EtsTable)) of @@ -251,8 +262,11 @@ to_dets(EtsTable, DetsTable) -> erlang:error(Unexpected,[EtsTable,DetsTable]) end. --spec test_ms(tuple(), match_specs()) -> - {'ok', term()} | {'error', [{'warning'|'error', string()}]}. +-spec test_ms(Tuple, MatchSpec) -> {'ok', Result} | {'error', Errors} when + Tuple :: tuple(), + MatchSpec :: match_spec(), + Result :: term(), + Errors :: [{'warning'|'error', string()}]. test_ms(Term, MS) -> case erlang:match_spec_test(Term, MS, table) of @@ -262,7 +276,11 @@ test_ms(Term, MS) -> Error end. --spec init_table(tab(), fun(('read' | 'close') -> term())) -> 'true'. +-spec init_table(Tab, InitFun) -> 'true' when + Tab :: tab(), + InitFun :: fun((Arg) -> Res), + Arg :: 'read' | 'close', + Res :: 'end_of_input' | {Objects :: [term()], InitFun} | term(). init_table(Table, Fun) -> ets:delete_all_objects(Table), @@ -287,7 +305,9 @@ init_table_sub(Table, [H|T]) -> ets:insert(Table, H), init_table_sub(Table, T). --spec match_delete(tab(), match_pattern()) -> 'true'. +-spec match_delete(Tab, Pattern) -> 'true' when + Tab :: tab(), + Pattern :: match_pattern(). match_delete(Table, Pattern) -> ets:select_delete(Table, [{Pattern,[],[true]}]), @@ -295,7 +315,9 @@ match_delete(Table, Pattern) -> %% Produce a list of tuples from a table --spec tab2list(tab()) -> [tuple()]. +-spec tab2list(Tab) -> [Object] when + Tab :: tab(), + Object :: tuple(). tab2list(T) -> ets:match_object(T, '_'). @@ -334,15 +356,21 @@ do_filter(Tab, Key, F, A, Ack) -> md5sum = false :: boolean() }). --type fname() :: string() | atom(). --type t2f_option() :: {'extended_info', [ext_info()]}. - --spec tab2file(tab(), fname()) -> 'ok' | {'error', term()}. +-spec tab2file(Tab, Filename) -> 'ok' | {'error', Reason} when + Tab :: tab(), + Filename :: file:name(), + Reason :: term(). tab2file(Tab, File) -> tab2file(Tab, File, []). --spec tab2file(tab(), fname(), [t2f_option()]) -> 'ok' | {'error', term()}. +-spec tab2file(Tab, Filename, Options) -> 'ok' | {'error', Reason} when + Tab :: tab(), + Filename :: file:name(), + Options :: [Option], + Option :: {'extended_info', [ExtInfo]}, + ExtInfo :: 'md5sum' | 'object_count', + Reason :: term(). tab2file(Tab, File, Options) -> try @@ -501,14 +529,20 @@ parse_ft_info_options(_,Malformed) -> %% Opt := {verify,boolean()} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --type f2t_option() :: {'verify', boolean()}. - --spec file2tab(fname()) -> {'ok', tab()} | {'error', term()}. +-spec file2tab(Filename) -> {'ok', Tab} | {'error', Reason} when + Filename :: file:name(), + Tab :: tab(), + Reason :: term(). file2tab(File) -> file2tab(File, []). --spec file2tab(fname(), [f2t_option()]) -> {'ok', tab()} | {'error', term()}. +-spec file2tab(Filename, Options) -> {'ok', Tab} | {'error', Reason} when + Filename :: file:name(), + Tab :: tab(), + Options :: [Option], + Option :: {'verify', boolean()}, + Reason :: term(). file2tab(File, Opts) -> try @@ -895,7 +929,22 @@ named_table(false) -> []. %% information %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec tabfile_info(fname()) -> {'ok', [table_info()]} | {'error', term()}. +-spec tabfile_info(Filename) -> {'ok', TableInfo} | {'error', Reason} when + Filename :: file:name(), + TableInfo :: [InfoItem], + InfoItem :: {'name', atom()} + | {'type', Type} + | {'protection', Protection} + | {'named_table', boolean()} + | {'keypos', non_neg_integer()} + | {'size', non_neg_integer()} + | {'extended_info', [ExtInfo]} + | {'version', {Major :: non_neg_integer(), + Minor :: non_neg_integer()}}, + ExtInfo :: 'md5sum' | 'object_count', + Type :: 'bag' | 'duplicate_bag' | 'ordered_set' | 'set', + Protection :: 'private' | 'protected' | 'public', + Reason :: term(). tabfile_info(File) when is_list(File) ; is_atom(File) -> try @@ -932,20 +981,22 @@ tabfile_info(File) when is_list(File) ; is_atom(File) -> {error,ExReason} end. --type qlc__query_handle() :: term(). %% XXX: belongs in 'qlc' - --type num_objects() :: 'default' | pos_integer(). --type trav_method() :: 'first_next' | 'last_prev' - | 'select' | {'select', match_specs()}. --type table_option() :: {'n_objects', num_objects()} - | {'traverse', trav_method()}. - --spec table(tab()) -> qlc__query_handle(). +-spec table(Tab) -> QueryHandle when + Tab :: tab(), + QueryHandle :: qlc:query_handle(). table(Tab) -> table(Tab, []). --spec table(tab(), table_option() | [table_option()]) -> qlc__query_handle(). +-spec table(Tab, Options) -> QueryHandle when + Tab :: tab(), + QueryHandle :: qlc:query_handle(), + Options :: [Option] | Option, + Option :: {'n_objects', NObjects} + | {'traverse', TraverseMethod}, + NObjects :: 'default' | pos_integer(), + TraverseMethod :: 'first_next' | 'last_prev' + | 'select' | {'select', MatchSpec :: match_spec()}. table(Tab, Opts) -> case options(Opts, [traverse, n_objects]) of @@ -1135,7 +1186,8 @@ to_string(X) -> lists:flatten(io_lib:format("~p", [X])). %% view a specific table --spec i(tab()) -> 'ok'. +-spec i(Tab) -> 'ok' when + Tab :: tab(). i(Tab) -> i(Tab, 40). diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl index 2cbd6cdae7..f40904df1c 100644 --- a/lib/stdlib/src/eval_bits.erl +++ b/lib/stdlib/src/eval_bits.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,15 +31,16 @@ %% @type evalfun(). A closure which evaluates an expression given an %% environment %% -%% @type matchfun(). A closure which performs a match given a value, a -%% pattern and an environment +%% @type matchfun(). A closure which depending on its first argument +%% can perform a match (given a value, a pattern and an environment), +%% lookup a variable in the bindings, or add a new binding %% -%% @type field() represents a field in a "bin" +%% @type field(). Represents a field in a "bin". %%% Part 1: expression evaluation (binary construction) %% @spec expr_grp(Fields::[field()], Bindings::bindings(), -%% EvalFun::evalfun()) -> +%% EvalFun::evalfun(), term(), term()) -> %% {value, binary(), bindings()} %% %% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary @@ -144,7 +145,8 @@ eval_exp_field(Val, Size, Unit, binary, _, _) -> bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun) -> bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, true). -bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag) -> +bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag) + when is_function(Mfun, 2), is_function(Efun, 2) -> case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun) of {match,Bs,BBs,Rest} -> bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, Flag); @@ -175,14 +177,14 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0}, {Size1, [Type,{unit,Unit},Sign,Endian]} = make_bit_type(Line, Size0, Options0), V = erl_eval:partial_eval(VE), - match_check_size(Size1, BBs0), + match_check_size(Mfun, Size1, BBs0), {value, Size, _BBs} = Efun(Size1, BBs0), case catch get_value(Bin, Type, Size, Unit, Sign, Endian) of {Val,<<_/bitstring>>=Rest} -> NewV = coerce_to_float(V, Type), - case catch Mfun(NewV, Val, Bs0) of + case catch Mfun(match, {NewV,Val,Bs0}) of {match,Bs} -> - BBs = add_bin_binding(NewV, Bs, BBs0), + BBs = add_bin_binding(Mfun, NewV, Bs, BBs0), {match,Bs,BBs,Rest}; _ -> {nomatch,Rest} @@ -192,9 +194,9 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0}, end. %%% Part 3: binary pattern matching -%% @spec match_bits(Fields::[field()], Bin::binary() +%% @spec match_bits(Fields::[field()], Bin::binary(), %% GlobalEnv::bindings(), LocalEnv::bindings(), -%% MatchFun::matchfun(),EvalFun::evalfun()) -> +%% MatchFun::matchfun(),EvalFun::evalfun(), term()) -> %% {match, bindings()} %% @doc Used to perform matching. If the match succeeds a new %% environment is returned. If the match have some syntactic or @@ -205,7 +207,8 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0}, match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, _) -> match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun). -match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) -> +match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) + when is_function(Mfun, 2), is_function(Efun, 2) -> case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun) of {match,Bs} -> {match,Bs}; invalid -> throw(invalid); @@ -230,12 +233,12 @@ match_field_1({bin_element,Line,VE,Size0,Options0}, make_bit_type(Line, Size0, Options0), V = erl_eval:partial_eval(VE), Size2 = erl_eval:partial_eval(Size1), - match_check_size(Size2, BBs0), + match_check_size(Mfun, Size2, BBs0), {value, Size, _BBs} = Efun(Size2, BBs0), {Val,Rest} = get_value(Bin, Type, Size, Unit, Sign, Endian), NewV = coerce_to_float(V, Type), - {match,Bs} = Mfun(NewV, Val, Bs0), - BBs = add_bin_binding(NewV, Bs, BBs0), + {match,Bs} = Mfun(match, {NewV,Val,Bs0}), + BBs = add_bin_binding(Mfun, NewV, Bs, BBs0), {Bs,BBs,Rest}. %% Almost identical to the one in sys_pre_expand. @@ -249,12 +252,12 @@ coerce_to_float({integer,L,I}=E, float) -> coerce_to_float(E, _Type) -> E. -add_bin_binding({var,_,'_'}, _Bs, BBs) -> +add_bin_binding(_, {var,_,'_'}, _Bs, BBs) -> BBs; -add_bin_binding({var,_,Name}, Bs, BBs) -> - {value,Value} = erl_eval:binding(Name, Bs), - erl_eval:add_binding(Name, Value, BBs); -add_bin_binding(_, _Bs, BBs) -> +add_bin_binding(Mfun, {var,_,Name}, Bs, BBs) -> + {value,Value} = Mfun(binding, {Name,Bs}), + Mfun(add_binding, {Name,Value,BBs}); +add_bin_binding(_, _, _Bs, BBs) -> BBs. get_value(Bin, integer, Size, Unit, Sign, Endian) -> @@ -327,20 +330,20 @@ make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all' {error,Reason} -> error(Reason) end. -match_check_size({var,_,V}, Bs) -> - case erl_eval:binding(V, Bs) of +match_check_size(Mfun, {var,_,V}, Bs) -> + case Mfun(binding, {V,Bs}) of {value,_} -> ok; unbound -> throw(invalid) % or, rather, error({unbound,V}) end; -match_check_size({atom,_,all}, _Bs) -> +match_check_size(_, {atom,_,all}, _Bs) -> ok; -match_check_size({atom,_,undefined}, _Bs) -> +match_check_size(_, {atom,_,undefined}, _Bs) -> ok; -match_check_size({integer,_,_}, _Bs) -> +match_check_size(_, {integer,_,_}, _Bs) -> ok; -match_check_size({value,_,_}, _Bs) -> +match_check_size(_, {value,_,_}, _Bs) -> ok; %From the debugger. -match_check_size(_, _Bs) -> +match_check_size(_, _, _Bs) -> throw(invalid). %% error(Reason) -> exception thrown diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl index 2a5b08b581..3f31852afc 100644 --- a/lib/stdlib/src/file_sorter.erl +++ b/lib/stdlib/src/file_sorter.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -50,12 +50,68 @@ %%% Exported functions %%% +-export_type([reason/0]). + +-type(file_name() :: file:name()). +-type(file_names() :: [file:name()]). +-type(i_command() :: read | close). +-type(i_reply() :: end_of_input | {end_of_input, value()} + | {[object()], infun()} | input_reply()). +-type(infun() :: fun((i_command()) -> i_reply())). +-type(input() :: file_names() | infun()). +-type(input_reply() :: term()). +-type(o_command() :: {value, value()} | [object()] | close). +-type(o_reply() :: outfun() | output_reply()). +-type(object() :: term() | binary()). +-type(outfun() :: fun((o_command()) -> o_reply())). +-type(output() :: file_name() | outfun()). +-type(output_reply() :: term()). +-type(value() :: term()). + +-type(options() :: [option()] | option()). +-type(option() :: {compressed, boolean()} + | {header, header_length()} + | {format, format()} + | {no_files, no_files()} + | {order, order()} + | {size, size()} + | {tmpdir, tmp_directory()} + | {unique, boolean()}). +-type(format() :: binary_term | term | binary | format_fun()). +-type(format_fun() :: fun((binary()) -> term())). +-type(header_length() :: pos_integer()). +-type(key_pos() :: pos_integer() | [pos_integer()]). +-type(no_files() :: pos_integer()). % > 1 +-type(order() :: ascending | descending | order_fun()). +-type(order_fun() :: fun((term(), term()) -> boolean())). +-type(size() :: non_neg_integer()). +-type(tmp_directory() :: [] | file:name()). + +-type(reason() :: bad_object + | {bad_object, file_name()} + | {bad_term, file_name()} + | {file_error, file_name(), + file:posix() | badarg | system_limit} + | {premature_eof, file_name()}). + +-spec(sort(FileName) -> Reply when + FileName :: file_name(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). sort(FileName) -> sort([FileName], FileName). +-spec(sort(Input, Output) -> Reply when + Input :: input(), + Output :: output(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). sort(Input, Output) -> sort(Input, Output, []). +-spec(sort(Input, Output, Options) -> Reply when + Input :: input(), + Output :: output(), + Options :: options(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). sort(Input0, Output0, Options) -> case {is_input(Input0), maybe_output(Output0), options(Options)} of {{true,Input}, {true,Output}, #opts{}=Opts} -> @@ -64,12 +120,27 @@ sort(Input0, Output0, Options) -> badarg(culprit(tuple_to_list(T)), [Input0, Output0, Options]) end. +-spec(keysort(KeyPos, FileName) -> Reply when + KeyPos :: key_pos(), + FileName :: file_name(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). keysort(KeyPos, FileName) -> keysort(KeyPos, [FileName], FileName). +-spec(keysort(KeyPos, Input, Output) -> Reply when + KeyPos :: key_pos(), + Input :: input(), + Output :: output(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). keysort(KeyPos, Input, Output) -> keysort(KeyPos, Input, Output, []). +-spec(keysort(KeyPos, Input, Output, Options) -> Reply when + KeyPos :: key_pos(), + Input :: input(), + Output :: output(), + Options :: options(), + Reply :: ok | {error, reason()} | input_reply() | output_reply()). keysort(KeyPos, Input0, Output0, Options) -> R = case {is_keypos(KeyPos), is_input(Input0), maybe_output(Output0), options(Options)} of @@ -89,9 +160,18 @@ keysort(KeyPos, Input0, Output0, Options) -> badarg(culprit(O), [KeyPos, Input0, Output0, Options]) end. +-spec(merge(FileNames, Output) -> Reply when + FileNames :: file_names(), + Output :: output(), + Reply :: ok | {error, reason()} | output_reply()). merge(Files, Output) -> merge(Files, Output, []). +-spec(merge(FileNames, Output, Options) -> Reply when + FileNames :: file_names(), + Output :: output(), + Options :: options(), + Reply :: ok | {error, reason()} | output_reply()). merge(Files0, Output0, Options) -> case {is_files(Files0), maybe_output(Output0), options(Options)} of %% size not used @@ -101,9 +181,20 @@ merge(Files0, Output0, Options) -> badarg(culprit(tuple_to_list(T)), [Files0, Output0, Options]) end. +-spec(keymerge(KeyPos, FileNames, Output) -> Reply when + KeyPos :: key_pos(), + FileNames :: file_names(), + Output :: output(), + Reply :: ok | {error, reason()} | output_reply()). keymerge(KeyPos, Files, Output) -> keymerge(KeyPos, Files, Output, []). +-spec(keymerge(KeyPos, FileNames, Output, Options) -> Reply when + KeyPos :: key_pos(), + FileNames :: file_names(), + Output :: output(), + Options :: options(), + Reply :: ok | {error, reason()} | output_reply()). keymerge(KeyPos, Files0, Output0, Options) -> R = case {is_keypos(KeyPos), is_files(Files0), maybe_output(Output0), options(Options)} of @@ -123,9 +214,21 @@ keymerge(KeyPos, Files0, Output0, Options) -> badarg(culprit(O), [KeyPos, Files0, Output0, Options]) end. +-spec(check(FileName) -> Reply when + FileName :: file_name(), + Reply :: {ok, [Result]} | {error, reason()}, + Result :: {FileName, TermPosition, term()}, + TermPosition :: pos_integer()). check(FileName) -> check([FileName], []). +-spec(check(FileNames, Options) -> Reply when + FileNames :: file_names(), + Options :: options(), + Reply :: {ok, [Result]} | {error, reason()}, + Result :: {FileName, TermPosition, term()}, + FileName :: file_name(), + TermPosition :: pos_integer()). check(Files0, Options) -> case {is_files(Files0), options(Options)} of {{true,Files}, #opts{}=Opts} -> @@ -134,9 +237,23 @@ check(Files0, Options) -> badarg(culprit(tuple_to_list(T)), [Files0, Options]) end. +-spec(keycheck(KeyPos, FileName) -> Reply when + KeyPos :: key_pos(), + FileName :: file_name(), + Reply :: {ok, [Result]} | {error, reason()}, + Result :: {FileName, TermPosition, term()}, + TermPosition :: pos_integer()). keycheck(KeyPos, FileName) -> keycheck(KeyPos, [FileName], []). +-spec(keycheck(KeyPos, FileNames, Options) -> Reply when + KeyPos :: key_pos(), + FileNames :: file_names(), + Options :: options(), + Reply :: {ok, [Result]} | {error, reason()}, + Result :: {FileName, TermPosition, term()}, + FileName :: file_name(), + TermPosition :: pos_integer()). keycheck(KeyPos, Files0, Options) -> R = case {is_keypos(KeyPos), is_files(Files0), options(Options)} of {_, _, #opts{format = binary}} -> diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl index c845b61204..d532cea187 100644 --- a/lib/stdlib/src/filelib.erl +++ b/lib/stdlib/src/filelib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,13 +40,19 @@ erlang:error(UnUsUalVaRiAbLeNaMe) end). +-type filename() :: file:name(). +-type dirname() :: filename(). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec wildcard(file:name()) -> [file:filename()]. +-spec wildcard(Wildcard) -> [file:filename()] when + Wildcard :: filename() | dirname(). wildcard(Pattern) when is_list(Pattern) -> ?HANDLE_ERROR(do_wildcard(Pattern, file)). --spec wildcard(file:name(), file:name() | atom()) -> [file:filename()]. +-spec wildcard(Wildcard, Cwd) -> [file:filename()] when + Wildcard :: filename() | dirname(), + Cwd :: dirname(). wildcard(Pattern, Cwd) when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)) -> ?HANDLE_ERROR(do_wildcard(Pattern, Cwd, file)); wildcard(Pattern, Mod) when is_list(Pattern), is_atom(Mod) -> @@ -57,7 +63,8 @@ wildcard(Pattern, Cwd, Mod) when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)), is_atom(Mod) -> ?HANDLE_ERROR(do_wildcard(Pattern, Cwd, Mod)). --spec is_dir(file:name()) -> boolean(). +-spec is_dir(Name) -> boolean() when + Name :: filename() | dirname(). is_dir(Dir) -> do_is_dir(Dir, file). @@ -65,7 +72,8 @@ is_dir(Dir) -> is_dir(Dir, Mod) when is_atom(Mod) -> do_is_dir(Dir, Mod). --spec is_file(file:name()) -> boolean(). +-spec is_file(Name) -> boolean() when + Name :: filename() | dirname(). is_file(File) -> do_is_file(File, file). @@ -73,7 +81,8 @@ is_file(File) -> is_file(File, Mod) when is_atom(Mod) -> do_is_file(File, Mod). --spec is_regular(file:name()) -> boolean(). +-spec is_regular(Name) -> boolean() when + Name :: filename(). is_regular(File) -> do_is_regular(File, file). @@ -81,7 +90,13 @@ is_regular(File) -> is_regular(File, Mod) when is_atom(Mod) -> do_is_regular(File, Mod). --spec fold_files(file:name(), string(), boolean(), fun((_,_) -> _), _) -> _. +-spec fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut when + Dir :: dirname(), + RegExp :: string(), + Recursive :: boolean(), + Fun :: fun((F :: file:filename(), AccIn) -> AccOut), + AccIn :: term(), + AccOut :: term(). fold_files(Dir, RegExp, Recursive, Fun, Acc) -> do_fold_files(Dir, RegExp, Recursive, Fun, Acc, file). @@ -89,7 +104,8 @@ fold_files(Dir, RegExp, Recursive, Fun, Acc) -> fold_files(Dir, RegExp, Recursive, Fun, Acc, Mod) when is_atom(Mod) -> do_fold_files(Dir, RegExp, Recursive, Fun, Acc, Mod). --spec last_modified(file:name()) -> file:date_time() | 0. +-spec last_modified(Name) -> file:date_time() | 0 when + Name :: filename() | dirname(). last_modified(File) -> do_last_modified(File, file). @@ -97,7 +113,8 @@ last_modified(File) -> last_modified(File, Mod) when is_atom(Mod) -> do_last_modified(File, Mod). --spec file_size(file:name()) -> non_neg_integer(). +-spec file_size(Filename) -> non_neg_integer() when + Filename :: filename(). file_size(File) -> do_file_size(File, file). @@ -237,7 +254,9 @@ do_file_size(File, Mod) -> %% +type X = filename() | dirname() %% ensures that the directory name required to create D exists --spec ensure_dir(file:name()) -> 'ok' | {'error', file:posix()}. +-spec ensure_dir(Name) -> 'ok' | {'error', Reason} when + Name :: filename() | dirname(), + Reason :: file:posix(). ensure_dir("/") -> ok; ensure_dir(F) -> diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 24abf1e977..1cb9e4a25e 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -61,12 +61,15 @@ %% (for WIN32): absname("/") -> "D:/" --spec absname(file:name()) -> file:filename(). +-spec absname(Filename) -> file:filename() when + Filename :: file:name(). absname(Name) -> {ok, Cwd} = file:get_cwd(), absname(Name, Cwd). --spec absname(file:name(), file:filename()) -> file:filename(). +-spec absname(Filename, Dir) -> file:filename() when + Filename :: file:name(), + Dir :: file:filename(). absname(Name, AbsBase) when is_binary(Name), is_list(AbsBase) -> absname(Name,filename_string_to_binary(AbsBase)); absname(Name, AbsBase) when is_list(Name), is_binary(AbsBase) -> @@ -119,7 +122,9 @@ absname_vr([[X, $:]|Name], _, _AbsBase) -> %% This is just a join/2, but assumes that %% AbsBase must be absolute and Name must be relative. --spec absname_join(file:filename(), file:name()) -> file:filename(). +-spec absname_join(Dir, Filename) -> file:filename() when + Dir :: file:filename(), + Filename :: file:name(). absname_join(AbsBase, Name) -> join(AbsBase, flatten(Name)). @@ -131,7 +136,8 @@ absname_join(AbsBase, Name) -> %% basename("/usr/foo/") -> "foo" (trailing slashes ignored) %% basename("/") -> [] --spec basename(file:name()) -> file:filename(). +-spec basename(Filename) -> file:filename() when + Filename :: file:name(). basename(Name) when is_binary(Name) -> case os:type() of {win32,_} -> @@ -192,7 +198,9 @@ skip_prefix(Name, _) -> %% rootname(basename("xxx.jam")) -> "xxx" %% rootname(basename("xxx.erl")) -> "xxx" --spec basename(file:name(), file:name()) -> file:filename(). +-spec basename(Filename, Ext) -> file:filename() when + Filename :: file:name(), + Ext :: file:name(). basename(Name, Ext) when is_binary(Name), is_list(Ext) -> basename(Name,filename_string_to_binary(Ext)); basename(Name, Ext) when is_list(Name), is_binary(Ext) -> @@ -240,7 +248,8 @@ basename([], _Ext, Tail, _DrvSep2) -> %% Example: dirname("/usr/src/kalle.erl") -> "/usr/src", %% dirname("kalle.erl") -> "." --spec dirname(file:name()) -> file:filename(). +-spec dirname(Filename) -> file:filename() when + Filename :: file:name(). dirname(Name) when is_binary(Name) -> {Dsep,Drivesep} = separators(), SList = case Dsep of @@ -332,7 +341,8 @@ dirjoin1([H|T],Acc,Sep) -> %% %% On Windows: fn:dirname("\\usr\\src/kalle.erl") -> "/usr/src" --spec extension(file:name()) -> file:filename(). +-spec extension(Filename) -> file:filename() when + Filename :: file:name(). extension(Name) when is_binary(Name) -> {Dsep,_} = separators(), SList = case Dsep of @@ -374,7 +384,8 @@ extension([], Result, _OsType) -> %% Joins a list of filenames with directory separators. --spec join([file:filename()]) -> file:filename(). +-spec join(Components) -> file:filename() when + Components :: [file:filename()]. join([Name1, Name2|Rest]) -> join([join(Name1, Name2)|Rest]); join([Name]) when is_list(Name) -> @@ -386,7 +397,9 @@ join([Name]) when is_atom(Name) -> %% Joins two filenames with directory separators. --spec join(file:filename(), file:filename()) -> file:filename(). +-spec join(Name1, Name2) -> file:filename() when + Name1 :: file:filename(), + Name2 :: file:filename(). join(Name1, Name2) when is_list(Name1), is_list(Name2) -> OsType = major_os_type(), case pathtype(Name2) of @@ -494,7 +507,8 @@ append(Dir, Name) -> %% current working volume. (Windows only) %% Example: a:bar.erl, /temp/foo.erl --spec pathtype(file:name()) -> 'absolute' | 'relative' | 'volumerelative'. +-spec pathtype(Path) -> 'absolute' | 'relative' | 'volumerelative' when + Path :: file:name(). pathtype(Atom) when is_atom(Atom) -> pathtype(atom_to_list(Atom)); pathtype(Name) when is_list(Name) or is_binary(Name) -> @@ -547,7 +561,8 @@ win32_pathtype(_) -> relative. %% Examples: rootname("/jam.src/kalle") -> "/jam.src/kalle" %% rootname("/jam.src/foo.erl") -> "/jam.src/foo" --spec rootname(file:name()) -> file:filename(). +-spec rootname(Filename) -> file:filename() when + Filename :: file:name(). rootname(Name) when is_binary(Name) -> list_to_binary(rootname(binary_to_list(Name))); % No need to handle unicode, . is < 128 rootname(Name0) -> @@ -576,7 +591,9 @@ rootname([], Root, _Ext, _OsType) -> %% Examples: rootname("/jam.src/kalle.jam", ".erl") -> "/jam.src/kalle.jam" %% rootname("/jam.src/foo.erl", ".erl") -> "/jam.src/foo" --spec rootname(file:name(), file:name()) -> file:filename(). +-spec rootname(Filename, Ext) -> file:filename() when + Filename :: file:name(), + Ext :: file:name(). rootname(Name, Ext) when is_binary(Name), is_binary(Ext) -> list_to_binary(rootname(binary_to_list(Name),binary_to_list(Ext))); rootname(Name, Ext) when is_binary(Name) -> @@ -602,7 +619,9 @@ rootname2([Char|Rest], Ext, Result) when is_integer(Char) -> %% split("foo/bar") -> ["foo", "bar"] %% split("a:\\msdev\\include") -> ["a:/", "msdev", "include"] --spec split(file:name()) -> [file:filename()]. +-spec split(Filename) -> Components when + Filename :: file:name(), + Components :: [file:filename()]. split(Name) when is_binary(Name) -> case os:type() of {win32, _} -> win32_splitb(Name); @@ -695,7 +714,8 @@ split([], Comp, Components, OsType) -> %% will be converted to backslashes. On all platforms, the %% name will be normalized as done by join/1. --spec nativename(file:filename()) -> file:filename(). +-spec nativename(Path) -> file:filename() when + Path :: file:filename(). nativename(Name0) -> Name = join([Name0]), %Normalize. case os:type() of @@ -747,12 +767,17 @@ separators() -> %% The paths in the {outdir, Path} and {i, Path} options are guaranteed %% to be absolute. --type rule() :: {string(), string()}. --type ecode() :: 'non_existing' | 'preloaded' | 'interpreted'. --type option() :: {'i', string()} | {'outdir', string()} | {'d', atom()}. - --spec find_src(atom() | string()) -> - {string(), [option()]} | {'error', {ecode(), atom()}}. +-spec find_src(Beam) -> {SourceFile, Options} + | {error, {ErrorReason, Module}} when + Beam :: Module | Filename, + Filename :: atom() | string(), + Module :: module(), + SourceFile :: string(), + Options :: [Option], + Option :: {'i', Path :: string()} + | {'outdir', Path :: string()} + | {'d', atom()}, + ErrorReason :: 'non_existing' | 'preloaded' | 'interpreted'. find_src(Mod) -> Default = [{"", ""}, {"ebin", "src"}, {"ebin", "esrc"}], Rules = @@ -763,8 +788,18 @@ find_src(Mod) -> end, find_src(Mod, Rules). --spec find_src(atom() | string(), [rule()]) -> - {string(), [option()]} | {'error', {ecode(), atom()}}. +-spec find_src(Beam, Rules) -> {SourceFile, Options} + | {error, {ErrorReason, Module}} when + Beam :: Module | Filename, + Filename :: atom() | string(), + Rules :: [{BinSuffix :: string(), SourceSuffix :: string()}], + Module :: module(), + SourceFile :: string(), + Options :: [Option], + Option :: {'i', Path :: string()} + | {'outdir', Path :: string()} + | {'d', atom()}, + ErrorReason :: 'non_existing' | 'preloaded' | 'interpreted'. find_src(Mod, Rules) when is_atom(Mod) -> find_src(atom_to_list(Mod), Rules); find_src(File0, Rules) when is_list(File0) -> @@ -890,7 +925,8 @@ major_os_type() -> %% flatten(List) %% Flatten a list, also accepting atoms. --spec flatten(file:name()) -> file:filename(). +-spec flatten(Filename) -> file:filename() when + Filename :: file:name(). flatten(Bin) when is_binary(Bin) -> Bin; flatten(List) -> diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index fc5beb28b0..91d21d869c 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -197,6 +197,7 @@ %% Some types. -type gb_set_node() :: 'nil' | {term(), _, _}. +-opaque iter() :: [gb_set_node()]. %% A declaration equivalent to the following is currently hard-coded %% in erl_types.erl @@ -205,38 +206,47 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec empty() -> gb_set(). +-spec empty() -> Set when + Set :: gb_set(). empty() -> {0, nil}. --spec new() -> gb_set(). +-spec new() -> Set when + Set :: gb_set(). new() -> empty(). --spec is_empty(gb_set()) -> boolean(). +-spec is_empty(Set) -> boolean() when + Set :: gb_set(). is_empty({0, nil}) -> true; is_empty(_) -> false. --spec size(gb_set()) -> non_neg_integer(). +-spec size(Set) -> non_neg_integer() when + Set :: gb_set(). size({Size, _}) -> Size. --spec singleton(term()) -> gb_set(). +-spec singleton(Element) -> gb_set() when + Element :: term(). singleton(Key) -> {1, {Key, nil, nil}}. --spec is_element(term(), gb_set()) -> boolean(). +-spec is_element(Element, Set) -> boolean() when + Element :: term(), + Set :: gb_set(). is_element(Key, S) -> is_member(Key, S). --spec is_member(term(), gb_set()) -> boolean(). +-spec is_member(Element, Set) -> boolean() when + Element :: term(), + Set :: gb_set(). is_member(Key, {_, T}) -> is_member_1(Key, T). @@ -250,7 +260,10 @@ is_member_1(_, {_, _, _}) -> is_member_1(_, nil) -> false. --spec insert(term(), gb_set()) -> gb_set(). +-spec insert(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). insert(Key, {S, T}) -> S1 = S + 1, @@ -306,7 +319,9 @@ count({_, Sm, Bi}) -> count(nil) -> {1, 0}. --spec balance(gb_set()) -> gb_set(). +-spec balance(Set1) -> Set2 when + Set1 :: gb_set(), + Set2 :: gb_set(). balance({S, T}) -> {S, balance(T, S)}. @@ -331,12 +346,18 @@ balance_list_1([Key | L], 1) -> balance_list_1(L, 0) -> {nil, L}. --spec add_element(term(), gb_set()) -> gb_set(). +-spec add_element(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). add_element(X, S) -> add(X, S). --spec add(term(), gb_set()) -> gb_set(). +-spec add(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). add(X, S) -> case is_member(X, S) of @@ -346,23 +367,33 @@ add(X, S) -> insert(X, S) end. --spec from_list([term()]) -> gb_set(). +-spec from_list(List) -> Set when + List :: [term()], + Set :: gb_set(). from_list(L) -> from_ordset(ordsets:from_list(L)). --spec from_ordset([term()]) -> gb_set(). +-spec from_ordset(List) -> Set when + List :: [term()], + Set :: gb_set(). from_ordset(L) -> S = length(L), {S, balance_list(L, S)}. --spec del_element(term(), gb_set()) -> gb_set(). +-spec del_element(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). del_element(Key, S) -> delete_any(Key, S). --spec delete_any(term(), gb_set()) -> gb_set(). +-spec delete_any(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). delete_any(Key, S) -> case is_member(Key, S) of @@ -372,7 +403,10 @@ delete_any(Key, S) -> S end. --spec delete(term(), gb_set()) -> gb_set(). +-spec delete(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: gb_set(), + Set2 :: gb_set(). delete(Key, {S, T}) -> {S - 1, delete_1(Key, T)}. @@ -394,7 +428,10 @@ merge(Smaller, Larger) -> {Key, Larger1} = take_smallest1(Larger), {Key, Smaller, Larger1}. --spec take_smallest(gb_set()) -> {term(), gb_set()}. +-spec take_smallest(Set1) -> {Element, Set2} when + Set1 :: gb_set(), + Set2 :: gb_set(), + Element :: term(). take_smallest({S, T}) -> {Key, Larger} = take_smallest1(T), @@ -406,7 +443,8 @@ take_smallest1({Key, Smaller, Larger}) -> {Key1, Smaller1} = take_smallest1(Smaller), {Key1, {Key, Smaller1, Larger}}. --spec smallest(gb_set()) -> term(). +-spec smallest(Set) -> term() when + Set :: gb_set(). smallest({_, T}) -> smallest_1(T). @@ -416,7 +454,10 @@ smallest_1({Key, nil, _Larger}) -> smallest_1({_Key, Smaller, _Larger}) -> smallest_1(Smaller). --spec take_largest(gb_set()) -> {term(), gb_set()}. +-spec take_largest(Set1) -> {Element, Set2} when + Set1 :: gb_set(), + Set2 :: gb_set(), + Element :: term(). take_largest({S, T}) -> {Key, Smaller} = take_largest1(T), @@ -428,7 +469,8 @@ take_largest1({Key, Smaller, Larger}) -> {Key1, Larger1} = take_largest1(Larger), {Key1, {Key, Smaller, Larger1}}. --spec largest(gb_set()) -> term(). +-spec largest(Set) -> term() when + Set :: gb_set(). largest({_, T}) -> largest_1(T). @@ -438,7 +480,9 @@ largest_1({Key, _Smaller, nil}) -> largest_1({_Key, _Smaller, Larger}) -> largest_1(Larger). --spec to_list(gb_set()) -> [term()]. +-spec to_list(Set) -> List when + Set :: gb_set(), + List :: [term()]. to_list({_, T}) -> to_list(T, []). @@ -449,7 +493,9 @@ to_list({Key, Small, Big}, L) -> to_list(Small, [Key | to_list(Big, L)]); to_list(nil, L) -> L. --spec iterator(gb_set()) -> [term()]. +-spec iterator(Set) -> Iter when + Set :: gb_set(), + Iter :: iter(). iterator({_, T}) -> iterator(T, []). @@ -464,7 +510,10 @@ iterator({_, L, _} = T, As) -> iterator(nil, As) -> As. --spec next([term()]) -> {term(), [term()]} | 'none'. +-spec next(Iter1) -> {Element, Iter2} | 'none' when + Iter1 :: iter(), + Iter2 :: iter(), + Element :: term(). next([{X, _, T} | As]) -> {X, iterator(T, As)}; @@ -494,7 +543,10 @@ next([]) -> %% traversing the elements can be devised, but they all have higher %% overhead. --spec union(gb_set(), gb_set()) -> gb_set(). +-spec union(Set1, Set2) -> Set3 when + Set1 :: gb_set(), + Set2 :: gb_set(), + Set3 :: gb_set(). union({N1, T1}, {N2, T2}) when N2 < N1 -> union(to_list_1(T2), N2, T1, N1); @@ -596,7 +648,9 @@ balance_revlist_1([Key | L], 1) -> balance_revlist_1(L, 0) -> {nil, L}. --spec union([gb_set()]) -> gb_set(). +-spec union(SetList) -> Set when + SetList :: [gb_set(),...], + Set :: gb_set(). union([S | Ss]) -> union_list(S, Ss); @@ -609,7 +663,10 @@ union_list(S, []) -> S. %% The rest is modelled on the above. --spec intersection(gb_set(), gb_set()) -> gb_set(). +-spec intersection(Set1, Set2) -> Set3 when + Set1 :: gb_set(), + Set2 :: gb_set(), + Set3 :: gb_set(). intersection({N1, T1}, {N2, T2}) when N2 < N1 -> intersection(to_list_1(T2), N2, T1, N1); @@ -657,7 +714,9 @@ intersection_2([], _, As, S) -> intersection_2(_, [], As, S) -> {S, balance_revlist(As, S)}. --spec intersection([gb_set(),...]) -> gb_set(). +-spec intersection(SetList) -> Set when + SetList :: [gb_set(),...], + Set :: gb_set(). intersection([S | Ss]) -> intersection_list(S, Ss). @@ -666,7 +725,9 @@ intersection_list(S, [S1 | Ss]) -> intersection_list(intersection(S, S1), Ss); intersection_list(S, []) -> S. --spec is_disjoint(gb_set(), gb_set()) -> boolean(). +-spec is_disjoint(Set1, Set2) -> boolean() when + Set1 :: gb_set(), + Set2 :: gb_set(). is_disjoint({N1, T1}, {N2, T2}) when N1 < N2 -> is_disjoint_1(T1, T2); @@ -694,12 +755,18 @@ is_disjoint_1(_, nil) -> %% the sets. Therefore, we always build a new tree, and thus we need to %% traverse the whole element list of the left operand. --spec subtract(gb_set(), gb_set()) -> gb_set(). +-spec subtract(Set1, Set2) -> Set3 when + Set1 :: gb_set(), + Set2 :: gb_set(), + Set3 :: gb_set(). subtract(S1, S2) -> difference(S1, S2). --spec difference(gb_set(), gb_set()) -> gb_set(). +-spec difference(Set1, Set2) -> Set3 when + Set1 :: gb_set(), + Set2 :: gb_set(), + Set3 :: gb_set(). difference({N1, T1}, {N2, T2}) -> difference(to_list_1(T1), N1, T2, N2). @@ -747,7 +814,9 @@ difference_2(Xs, [], As, S) -> %% Subset testing is much the same thing as set difference, but %% without the construction of a new set. --spec is_subset(gb_set(), gb_set()) -> boolean(). +-spec is_subset(Set1, Set2) -> boolean() when + Set1 :: gb_set(), + Set2 :: gb_set(). is_subset({N1, T1}, {N2, T2}) -> is_subset(to_list_1(T1), N1, T2, N2). @@ -788,18 +857,28 @@ is_subset_2(_, []) -> %% For compatibility with `sets': --spec is_set(term()) -> boolean(). +-spec is_set(Term) -> boolean() when + Term :: term(). is_set({0, nil}) -> true; is_set({N, {_, _, _}}) when is_integer(N), N >= 0 -> true; is_set(_) -> false. --spec filter(fun((term()) -> boolean()), gb_set()) -> gb_set(). +-spec filter(Pred, Set1) -> Set2 when + Pred :: fun((E :: term()) -> boolean()), + Set1 :: gb_set(), + Set2 :: gb_set(). filter(F, S) -> from_ordset([X || X <- to_list(S), F(X)]). --spec fold(fun((term(), term()) -> term()), term(), gb_set()) -> term(). +-spec fold(Function, Acc0, Set) -> Acc1 when + Function :: fun((E :: term(), AccIn) -> AccOut), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + Set :: gb_set(). fold(F, A, {_, T}) when is_function(F, 2) -> fold_1(F, A, T). diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl index d37786a100..6ad861ff5b 100644 --- a/lib/stdlib/src/gb_trees.erl +++ b/lib/stdlib/src/gb_trees.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -153,6 +153,7 @@ %% Some types. -type gb_tree_node() :: 'nil' | {_, _, _, _}. +-opaque iter() :: [gb_tree_node()]. %% A declaration equivalent to the following is currently hard-coded %% in erl_types.erl @@ -166,21 +167,26 @@ empty() -> {0, nil}. --spec is_empty(gb_tree()) -> boolean(). +-spec is_empty(Tree) -> boolean() when + Tree :: gb_tree(). is_empty({0, nil}) -> true; is_empty(_) -> false. --spec size(gb_tree()) -> non_neg_integer(). +-spec size(Tree) -> non_neg_integer() when + Tree :: gb_tree(). size({Size, _}) when is_integer(Size), Size >= 0 -> Size. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec lookup(term(), gb_tree()) -> 'none' | {'value', term()}. +-spec lookup(Key, Tree) -> 'none' | {'value', Val} when + Key :: term(), + Val :: term(), + Tree :: gb_tree(). lookup(Key, {_, T}) -> lookup_1(Key, T). @@ -205,7 +211,9 @@ lookup_1(_, nil) -> %% This is a specialized version of `lookup'. --spec is_defined(term(), gb_tree()) -> boolean(). +-spec is_defined(Key, Tree) -> boolean() when + Key :: term(), + Tree :: gb_tree(). is_defined(Key, {_, T}) -> is_defined_1(Key, T). @@ -223,7 +231,10 @@ is_defined_1(_, nil) -> %% This is a specialized version of `lookup'. --spec get(term(), gb_tree()) -> term(). +-spec get(Key, Tree) -> Val when + Key :: term(), + Tree :: gb_tree(), + Val :: term(). get(Key, {_, T}) -> get_1(Key, T). @@ -237,7 +248,11 @@ get_1(_, {_, Value, _, _}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec update(term(), term(), gb_tree()) -> gb_tree(). +-spec update(Key, Val, Tree1) -> Tree2 when + Key :: term(), + Val :: term(), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). update(Key, Val, {S, T}) -> T1 = update_1(Key, Val, T), @@ -254,7 +269,11 @@ update_1(Key, Value, {_, _, Smaller, Bigger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec insert(term(), term(), gb_tree()) -> gb_tree(). +-spec insert(Key, Val, Tree1) -> Tree2 when + Key :: term(), + Val :: term(), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). insert(Key, Val, {S, T}) when is_integer(S) -> S1 = S+1, @@ -303,7 +322,11 @@ insert_1(Key, _, _, _) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec enter(term(), term(), gb_tree()) -> gb_tree(). +-spec enter(Key, Val, Tree1) -> Tree2 when + Key :: term(), + Val :: term(), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). enter(Key, Val, T) -> case is_defined(Key, T) of @@ -326,7 +349,9 @@ count(nil) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec balance(gb_tree()) -> gb_tree(). +-spec balance(Tree1) -> Tree2 when + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). balance({S, T}) -> {S, balance(T, S)}. @@ -351,7 +376,9 @@ balance_list_1([{Key, Val} | L], 1) -> balance_list_1(L, 0) -> {nil, L}. --spec from_orddict([{_,_}]) -> gb_tree(). +-spec from_orddict(List) -> Tree when + List :: [{Key :: term(), Val :: term()}], + Tree :: gb_tree(). from_orddict(L) -> S = length(L), @@ -359,7 +386,10 @@ from_orddict(L) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec delete_any(term(), gb_tree()) -> gb_tree(). +-spec delete_any(Key, Tree1) -> Tree2 when + Key :: term(), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). delete_any(Key, T) -> case is_defined(Key, T) of @@ -371,7 +401,10 @@ delete_any(Key, T) -> %%% delete. Assumes that key is present. --spec delete(term(), gb_tree()) -> gb_tree(). +-spec delete(Key, Tree1) -> Tree2 when + Key :: term(), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). delete(Key, {S, T}) when is_integer(S), S >= 0 -> {S - 1, delete_1(Key, T)}. @@ -397,7 +430,11 @@ merge(Smaller, Larger) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec take_smallest(gb_tree()) -> {term(), term(), gb_tree()}. +-spec take_smallest(Tree1) -> {Key, Val, Tree2} when + Tree1 :: gb_tree(), + Tree2 :: gb_tree(), + Key :: term(), + Val :: term(). take_smallest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Larger} = take_smallest1(Tree), @@ -409,7 +446,10 @@ take_smallest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Smaller1} = take_smallest1(Smaller), {Key1, Value1, {Key, Value, Smaller1, Larger}}. --spec smallest(gb_tree()) -> {term(), term()}. +-spec smallest(Tree) -> {Key, Val} when + Tree :: gb_tree(), + Key :: term(), + Val :: term(). smallest({_, Tree}) -> smallest_1(Tree). @@ -419,7 +459,11 @@ smallest_1({Key, Value, nil, _Larger}) -> smallest_1({_Key, _Value, Smaller, _Larger}) -> smallest_1(Smaller). --spec take_largest(gb_tree()) -> {term(), term(), gb_tree()}. +-spec take_largest(Tree1) -> {Key, Val, Tree2} when + Tree1 :: gb_tree(), + Tree2 :: gb_tree(), + Key :: term(), + Val :: term(). take_largest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Smaller} = take_largest1(Tree), @@ -431,7 +475,10 @@ take_largest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Larger1} = take_largest1(Larger), {Key1, Value1, {Key, Value, Smaller, Larger1}}. --spec largest(gb_tree()) -> {term(), term()}. +-spec largest(Tree) -> {Key, Val} when + Tree :: gb_tree(), + Key :: term(), + Val :: term(). largest({_, Tree}) -> largest_1(Tree). @@ -443,7 +490,10 @@ largest_1({_Key, _Value, _Smaller, Larger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec to_list(gb_tree()) -> [{term(), term()}]. +-spec to_list(Tree) -> [{Key, Val}] when + Tree :: gb_tree(), + Key :: term(), + Val :: term(). to_list({_, T}) -> to_list(T, []). @@ -456,7 +506,9 @@ to_list(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec keys(gb_tree()) -> [term()]. +-spec keys(Tree) -> [Key] when + Tree :: gb_tree(), + Key :: term(). keys({_, T}) -> keys(T, []). @@ -467,7 +519,9 @@ keys(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec values(gb_tree()) -> [term()]. +-spec values(Tree) -> [Val] when + Tree :: gb_tree(), + Val :: term(). values({_, T}) -> values(T, []). @@ -478,7 +532,9 @@ values(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec iterator(gb_tree()) -> [gb_tree_node()]. +-spec iterator(Tree) -> Iter when + Tree :: gb_tree(), + Iter :: iter(). iterator({_, T}) -> iterator_1(T). @@ -496,7 +552,11 @@ iterator({_, _, L, _} = T, As) -> iterator(nil, As) -> As. --spec next([gb_tree_node()]) -> 'none' | {term(), term(), [gb_tree_node()]}. +-spec next(Iter1) -> 'none' | {Key, Val, Iter2} when + Iter1 :: iter(), + Iter2 :: iter(), + Key :: term(), + Val :: term(). next([{X, V, _, T} | As]) -> {X, V, iterator(T, As)}; @@ -505,7 +565,10 @@ next([]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec map(fun((term(), term()) -> term()), gb_tree()) -> gb_tree(). +-spec map(Function, Tree1) -> Tree2 when + Function :: fun((K :: term(), V1 :: term()) -> V2 :: term()), + Tree1 :: gb_tree(), + Tree2 :: gb_tree(). map(F, {Size, Tree}) when is_function(F, 2) -> {Size, map_1(F, Tree)}. diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 43df6f621d..574146b1cd 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -29,6 +29,8 @@ -export([init_it/6, init_it/7]). +-export([format_status_header/2]). + -define(default_timeout, 5000). %%----------------------------------------------------------------- @@ -315,3 +317,10 @@ debug_options(Opts) -> {ok, Options} -> sys:debug_options(Options); _ -> [] end. + +format_status_header(TagLine, Pid) when is_pid(Pid) -> + lists:concat([TagLine, " ", pid_to_list(Pid)]); +format_status_header(TagLine, RegName) when is_atom(RegName) -> + lists:concat([TagLine, " ", RegName]); +format_status_header(TagLine, Name) -> + {TagLine, Name}. diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl index b1e9e3a02f..9879b76391 100644 --- a/lib/stdlib/src/gen_event.erl +++ b/lib/stdlib/src/gen_event.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,14 +36,15 @@ add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3, swap_sup_handler/3, which_handlers/1, call/3, call/4, wake_hib/4]). --export([behaviour_info/1]). - -export([init_it/6, system_continue/3, system_terminate/4, system_code_change/4, format_status/2]). +-export_type([handler/0, handler_args/0, add_handler_ret/0, + del_handler_ret/0]). + -import(error_logger, [error_msg/2]). -define(reply(X), From ! {element(2,Tag), X}). @@ -57,14 +58,6 @@ %%% API %%%========================================================================= --spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}]. - -behaviour_info(callbacks) -> - [{init,1},{handle_event,2},{handle_call,2},{handle_info,2}, - {terminate,2},{code_change,3}]; -behaviour_info(_Other) -> - undefined. - %% gen_event:start(Handler) -> {ok, Pid} | {error, What} %% gen_event:add_handler(Handler, Mod, Args) -> ok | Other %% gen_event:notify(Handler, Event) -> ok @@ -75,45 +68,44 @@ behaviour_info(_Other) -> %% gen_event:which_handler(Handler) -> [Mod] %% gen_event:stop(Handler) -> ok - -%% handlers must export -%% Mod:init(Args) -> {ok, State} | Other -%% Mod:handle_event(Event, State) -> -%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2} -%% Mod:handle_info(Info, State) -> -%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2} -%% Mod:handle_call(Query, State) -> -%% {ok, Reply, State'} | {remove_handler, Reply} | -%% {swap_handler, Reply, Args1,State1,Mod2,Args2} -%% Mod:terminate(Args, State) -> Val - - -%% add_handler(H, Mod, Args) -> ok | Other -%% Mod:init(Args) -> {ok, State} | Other - -%% delete_handler(H, Mod, Args) -> Val -%% Mod:terminate(Args, State) -> Val - -%% notify(H, Event) -%% Mod:handle_event(Event, State) -> -%% {ok, State1} -%% remove_handler -%% Mod:terminate(remove_handler, State) is called -%% the return value is ignored -%% {swap_handler, Args1, State1, Mod2, Args2} -%% State2 = Mod:terminate(Args1, State1) is called -%% the return value is chained into the new module and -%% Mod2:init({Args2, State2}) is called -%% Other -%% Mod:terminate({error, Other}, State) is called -%% The return value is ignored -%% call(H, Mod, Query) -> Val -%% call(H, Mod, Query, Timeout) -> Val -%% Mod:handle_call(Query, State) -> as above +-callback init(InitArgs :: term()) -> + {ok, State :: term()} | + {ok, State :: term(), hibernate}. +-callback handle_event(Event :: term(), State :: term()) -> + {ok, NewState :: term()} | + {ok, NewState :: term(), hibernate} | + {swap_handler, Args1 :: term(), NewState :: term(), + Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} | + remove_handler. +-callback handle_call(Request :: term(), State :: term()) -> + {ok, Reply :: term(), NewState :: term()} | + {ok, Reply :: term(), NewState :: term(), hibernate} | + {swap_handler, Reply :: term(), Args1 :: term(), NewState :: term(), + Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} | + {remove_handler, Reply :: term()}. +-callback handle_info(Info :: term(), State :: term()) -> + {ok, NewState :: term()} | + {ok, NewState :: term(), hibernate} | + {swap_handler, Args1 :: term(), NewState :: term(), + Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} | + remove_handler. +-callback terminate(Args :: (term() | {stop, Reason :: term()} | + stop | remove_handler | + {error, {'EXIT', Reason :: term()}} | + {error, term()}), + State :: term()) -> + term(). +-callback code_change(OldVsn :: (term() | {down, term()}), + State :: term(), Extra :: term()) -> + {ok, NewState :: term()}. %%--------------------------------------------------------------------------- --type handler() :: atom() | {atom(), term()}. +-type handler() :: atom() | {atom(), term()}. +-type handler_args() :: term(). +-type add_handler_ret() :: ok | term() | {'EXIT',term()}. +-type del_handler_ret() :: ok | term() | {'EXIT',term()}. + -type emgr_name() :: {'local', atom()} | {'global', atom()}. -type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid(). -type start_ret() :: {'ok', pid()} | {'error', term()}. @@ -660,16 +652,16 @@ report_error(_Handler, {swapped,_,_}, _, _, _) -> ok; report_error(Handler, Reason, State, LastIn, SName) -> Reason1 = case Reason of - {'EXIT',{undef,[{M,F,A}|MFAs]}} -> + {'EXIT',{undef,[{M,F,A,L}|MFAs]}} -> case code:is_loaded(M) of false -> - {'module could not be loaded',[{M,F,A}|MFAs]}; + {'module could not be loaded',[{M,F,A,L}|MFAs]}; _ -> case erlang:function_exported(M, F, length(A)) of true -> - {undef,[{M,F,A}|MFAs]}; + {undef,[{M,F,A,L}|MFAs]}; false -> - {'function not exported',[{M,F,A}|MFAs]} + {'function not exported',[{M,F,A,L}|MFAs]} end end; {'EXIT',Why} -> @@ -724,7 +716,8 @@ get_modules(MSL) -> %%----------------------------------------------------------------- format_status(Opt, StatusData) -> [PDict, SysState, Parent, _Debug, [ServerName, MSL, _Hib]] = StatusData, - Header = lists:concat(["Status for event handler ", ServerName]), + Header = gen:format_status_header("Status for event handler", + ServerName), FmtMSL = [case erlang:function_exported(Mod, format_status, 2) of true -> Args = [PDict, State], diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index 7d9960b912..3db8c9f4f2 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -113,8 +113,6 @@ start_timer/2,send_event_after/2,cancel_timer/1, enter_loop/4, enter_loop/5, enter_loop/6, wake_hib/6]). --export([behaviour_info/1]). - %% Internal exports -export([init_it/6, system_continue/3, @@ -128,13 +126,38 @@ %%% Interface functions. %%% --------------------------------------------------- --spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}]. - -behaviour_info(callbacks) -> - [{init,1},{handle_event,3},{handle_sync_event,4},{handle_info,3}, - {terminate,3},{code_change,4}]; -behaviour_info(_Other) -> - undefined. +-callback init(Args :: term()) -> + {ok, StateName :: atom(), StateData :: term()} | + {ok, StateName :: atom(), StateData :: term(), timeout() | hibernate} | + {stop, Reason :: term()} | ignore. +-callback handle_event(Event :: term(), StateName :: atom(), + StateData :: term()) -> + {next_state, NextStateName :: atom(), NewStateData :: term()} | + {next_state, NextStateName :: atom(), NewStateData :: term(), + timeout() | hibernate} | + {stop, Reason :: term(), NewStateData :: term()}. +-callback handle_sync_event(Event :: term(), From :: {pid(), Tag :: term()}, + StateName :: atom(), StateData :: term()) -> + {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term()} | + {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term(), + timeout() | hibernate} | + {next_state, NextStateName :: atom(), NewStateData :: term()} | + {next_state, NextStateName :: atom(), NewStateData :: term(), + timeout() | hibernate} | + {stop, Reason :: term(), Reply :: term(), NewStateData :: term()} | + {stop, Reason :: term(), NewStateData :: term()}. +-callback handle_info(Info :: term(), StateName :: atom(), + StateData :: term()) -> + {next_state, NextStateName :: atom(), NewStateData :: term()} | + {next_state, NextStateName :: atom(), NewStateData :: term(), + timeout() | hibernate} | + {stop, Reason :: normal | term(), NewStateData :: term()}. +-callback terminate(Reason :: normal | shutdown | {shutdown, term()} + | term(), StateName :: atom(), StateData :: term()) -> + term(). +-callback code_change(OldVsn :: term() | {down, term()}, StateName :: atom(), + StateData :: term(), Extra :: term()) -> + {ok, NextStateName :: atom(), NewStateData :: term()}. %%% --------------------------------------------------- %%% Starts a generic state machine. @@ -561,16 +584,16 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) -> error_info(Reason, Name, Msg, StateName, StateData, Debug) -> Reason1 = case Reason of - {undef,[{M,F,A}|MFAs]} -> + {undef,[{M,F,A,L}|MFAs]} -> case code:is_loaded(M) of false -> - {'module could not be loaded',[{M,F,A}|MFAs]}; + {'module could not be loaded',[{M,F,A,L}|MFAs]}; _ -> case erlang:function_exported(M, F, length(A)) of true -> Reason; false -> - {'function not exported',[{M,F,A}|MFAs]} + {'function not exported',[{M,F,A,L}|MFAs]} end end; _ -> @@ -614,15 +637,8 @@ get_msg(Msg) -> Msg. format_status(Opt, StatusData) -> [PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] = StatusData, - StatusHdr = "Status for state machine", - Header = if - is_pid(Name) -> - lists:concat([StatusHdr, " ", pid_to_list(Name)]); - is_atom(Name); is_list(Name) -> - lists:concat([StatusHdr, " ", Name]); - true -> - {StatusHdr, Name} - end, + Header = gen:format_status_header("Status for state machine", + Name), Log = sys:get_debug(log, Debug, []), DefaultStatus = [{data, [{"StateData", StateData}]}], Specfic = diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index ac81df9cab..dd0ef74f30 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -94,8 +94,6 @@ multi_call/2, multi_call/3, multi_call/4, enter_loop/3, enter_loop/4, enter_loop/5, wake_hib/5]). --export([behaviour_info/1]). - %% System exports -export([system_continue/3, system_terminate/4, @@ -111,13 +109,32 @@ %%% API %%%========================================================================= --spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}]. - -behaviour_info(callbacks) -> - [{init,1},{handle_call,3},{handle_cast,2},{handle_info,2}, - {terminate,2},{code_change,3}]; -behaviour_info(_Other) -> - undefined. +-callback init(Args :: term()) -> + {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} | + {stop, Reason :: term()} | ignore. +-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()}, + State :: term()) -> + {reply, Reply :: term(), NewState :: term()} | + {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), Reply :: term(), NewState :: term()} | + {stop, Reason :: term(), NewState :: term()}. +-callback handle_cast(Request :: term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. +-callback handle_info(Info :: timeout() | term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. +-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} | + term()), + State :: term()) -> + term(). +-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), + Extra :: term()) -> + {ok, NewState :: term()}. %%% ----------------------------------------------------------------- %%% Starts a generic server. @@ -729,16 +746,16 @@ error_info(_Reason, application_controller, _Msg, _State, _Debug) -> error_info(Reason, Name, Msg, State, Debug) -> Reason1 = case Reason of - {undef,[{M,F,A}|MFAs]} -> + {undef,[{M,F,A,L}|MFAs]} -> case code:is_loaded(M) of false -> - {'module could not be loaded',[{M,F,A}|MFAs]}; + {'module could not be loaded',[{M,F,A,L}|MFAs]}; _ -> case erlang:function_exported(M, F, length(A)) of true -> Reason; false -> - {'function not exported',[{M,F,A}|MFAs]} + {'function not exported',[{M,F,A,L}|MFAs]} end end; _ -> @@ -840,15 +857,8 @@ name_to_pid(Name) -> %%----------------------------------------------------------------- format_status(Opt, StatusData) -> [PDict, SysState, Parent, Debug, [Name, State, Mod, _Time]] = StatusData, - StatusHdr = "Status for generic server", - Header = if - is_pid(Name) -> - lists:concat([StatusHdr, " ", pid_to_list(Name)]); - is_atom(Name); is_list(Name) -> - lists:concat([StatusHdr, " ", Name]); - true -> - {StatusHdr, Name} - end, + Header = gen:format_status_header("Status for generic server", + Name), Log = sys:get_debug(log, Debug, []), DefaultStatus = [{data, [{"State", State}]}], Specfic = diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl index 6aeb076a0b..9f65bbfa3a 100644 --- a/lib/stdlib/src/io.erl +++ b/lib/stdlib/src/io.erl @@ -41,6 +41,7 @@ -type error_description() :: term(). % Whatever the io-server sends. -type request_error() :: {'error',error_description()}. + %% XXX: Some uses of line() in this file may need to read erl_scan:location() -type line() :: pos_integer(). @@ -66,12 +67,15 @@ o_request(Io, Request, Func) -> end. %% Put chars takes mixed *unicode* list from R13 onwards. --spec put_chars(iodata()) -> 'ok'. +-spec put_chars(CharData) -> 'ok' when + CharData :: unicode:chardata(). put_chars(Chars) -> put_chars(default_output(), Chars). --spec put_chars(device(), iodata()) -> 'ok'. +-spec put_chars(IoDevice, IoData) -> 'ok' when + IoDevice :: device(), + IoData :: unicode:chardata(). put_chars(Io, Chars) -> o_request(Io, {put_chars,unicode,Chars}, put_chars). @@ -81,7 +85,8 @@ put_chars(Io, Chars) -> nl() -> nl(default_output()). --spec nl(device()) -> 'ok'. +-spec nl(IoDevice) -> 'ok' when + IoDevice :: device(). nl(Io) -> % o_request(Io, {put_chars,io_lib:nl()}). @@ -92,7 +97,8 @@ nl(Io) -> columns() -> columns(default_output()). --spec columns(device()) -> {'ok', pos_integer()} | {'error', 'enotsup'}. +-spec columns(IoDevice) -> {'ok', pos_integer()} | {'error', 'enotsup'} when + IoDevice :: device(). columns(Io) -> case request(Io, {get_geometry,columns}) of @@ -107,7 +113,8 @@ columns(Io) -> rows() -> rows(default_output()). --spec rows(device()) -> {'ok', pos_integer()} | {'error', 'enotsup'}. +-spec rows(IoDevice) -> {'ok', pos_integer()} | {'error', 'enotsup'} when + IoDevice :: device(). rows(Io) -> case request(Io,{get_geometry,rows}) of @@ -117,22 +124,36 @@ rows(Io) -> {error,enotsup} end. --spec get_chars(prompt(), non_neg_integer()) -> iodata() | 'eof'. +-spec get_chars(Prompt, Count) -> Data | 'eof' when + Prompt :: prompt(), + Count :: non_neg_integer(), + Data :: [unicode:unicode_char()] | unicode:unicode_binary(). get_chars(Prompt, N) -> get_chars(default_input(), Prompt, N). --spec get_chars(device(), prompt(), non_neg_integer()) -> iodata() | 'eof'. +-spec get_chars(IoDevice, Prompt, Count) -> Data | 'eof' | {error, Reason} when + IoDevice :: device(), + Prompt :: prompt(), + Count :: non_neg_integer(), + Reason :: term(), + Data :: [unicode:unicode_char()] | unicode:unicode_binary(). get_chars(Io, Prompt, N) when is_integer(N), N >= 0 -> request(Io, {get_chars,unicode,Prompt,N}). --spec get_line(prompt()) -> iodata() | 'eof' | {'error', term()}. +-spec get_line(Prompt) -> Data | 'eof' | {'error', Reason} when + Prompt :: prompt(), + Reason :: term(), + Data :: [unicode:unicode_char()] | unicode:unicode_binary(). get_line(Prompt) -> get_line(default_input(), Prompt). --spec get_line(device(), prompt()) -> iodata() | 'eof' | {'error', term()}. +-spec get_line(IoDevice, Prompt) -> Data | 'eof' | {'error', term()} when + IoDevice :: device(), + Prompt :: prompt(), + Data :: [unicode:unicode_char()] | unicode:unicode_binary(). get_line(Io, Prompt) -> request(Io, {get_line,unicode,Prompt}). @@ -156,46 +177,62 @@ get_password(Io) -> getopts() -> getopts(default_input()). --spec getopts(device()) -> [opt_pair()]. +-spec getopts(IoDevice) -> [opt_pair()] when + IoDevice :: device(). getopts(Io) -> request(Io, getopts). -type setopt() :: 'binary' | 'list' | opt_pair(). --spec setopts([setopt()]) -> 'ok' | {'error', term()}. +-spec setopts(Opts) -> 'ok' | {'error', Reason} when + Opts :: [setopt()], + Reason :: term(). setopts(Opts) -> setopts(default_input(), Opts). --spec setopts(device(), [setopt()]) -> 'ok' | {'error', term()}. +-spec setopts(IoDevice, Opts) -> 'ok' | {'error', Reason} when + IoDevice :: device(), + Opts :: [setopt()], + Reason :: term(). setopts(Io, Opts) -> request(Io, {setopts, Opts}). %% Writing and reading Erlang terms. --spec write(term()) -> 'ok'. +-spec write(Term) -> 'ok' when + Term :: term(). write(Term) -> write(default_output(), Term). --spec write(device(), term()) -> 'ok'. +-spec write(IoDevice, Term) -> 'ok' when + IoDevice :: device(), + Term :: term(). write(Io, Term) -> o_request(Io, {write,Term}, write). --spec read(prompt()) -> - {'ok', term()} | 'eof' | {'error', erl_scan:error_info()}. +-spec read(Prompt) -> Result when + Prompt :: prompt(), + Result :: {'ok', Term :: term()} + | 'eof' + | {'error', ErrorInfo :: erl_scan:error_info()}. % Read does not use get_until as erl_scan does not work with unicode % XXX:PaN fixme? read(Prompt) -> read(default_input(), Prompt). --spec read(device(), prompt()) -> - {'ok', term()} | 'eof' | {'error', erl_scan:error_info()}. +-spec read(IoDevice, Prompt) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + Result :: {'ok', Term :: term()} + | 'eof' + | {'error', ErrorInfo :: erl_scan:error_info()}. read(Io, Prompt) -> case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[1]}) of @@ -211,9 +248,13 @@ read(Io, Prompt) -> Other end. --spec read(device(), prompt(), line()) -> - {'ok', term(), line()} | {'eof', line()} | - {'error', erl_scan:error_info(), line()}. +-spec read(IoDevice, Prompt, StartLine) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + StartLine :: line(), + Result :: {'ok', Term :: term(), EndLine :: line()} + | {'eof', EndLine :: line()} + | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}. read(Io, Prompt, StartLine) when is_integer(StartLine) -> case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[StartLine]}) of @@ -239,28 +280,40 @@ conv_reason(_, _Reason) -> badarg. -type format() :: atom() | string() | binary(). --spec fwrite(format()) -> 'ok'. +-spec fwrite(Format) -> 'ok' when + Format :: format(). fwrite(Format) -> format(Format). --spec fwrite(format(), [term()]) -> 'ok'. +-spec fwrite(Format, Data) -> 'ok' when + Format :: format(), + Data :: [term()]. fwrite(Format, Args) -> format(Format, Args). --spec fwrite(device(), format(), [term()]) -> 'ok'. +-spec fwrite(IoDevice, Format, Data) -> 'ok' when + IoDevice :: device(), + Format :: format(), + Data :: [term()]. fwrite(Io, Format, Args) -> format(Io, Format, Args). --spec fread(prompt(), format()) -> {'ok', [term()]} | 'eof' | {'error',term()}. +-spec fread(Prompt, Format) -> Result when + Prompt :: prompt(), + Format :: format(), + Result :: {'ok', Terms :: [term()]} | 'eof' | {'error', What :: term()}. fread(Prompt, Format) -> fread(default_input(), Prompt, Format). --spec fread(device(), prompt(), format()) -> - {'ok', [term()]} | 'eof' | {'error',term()}. +-spec fread(IoDevice, Prompt, Format) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + Format :: format(), + Result :: {'ok', Terms :: [term()]} | 'eof' | {'error', What :: term()}. fread(Io, Prompt, Format) -> case request(Io, {fread,Prompt,Format}) of @@ -270,73 +323,104 @@ fread(Io, Prompt, Format) -> Other end. --spec format(format()) -> 'ok'. +-spec format(Format) -> 'ok' when + Format :: format(). format(Format) -> format(Format, []). --spec format(format(), [term()]) -> 'ok'. +-spec format(Format, Data) -> 'ok' when + Format :: format(), + Data :: [term()]. format(Format, Args) -> format(default_output(), Format, Args). --spec format(device(), format(), [term()]) -> 'ok'. +-spec format(IoDevice, Format, Data) -> 'ok' when + IoDevice :: device(), + Format :: format(), + Data :: [term()]. format(Io, Format, Args) -> o_request(Io, {format,Format,Args}, format). %% Scanning Erlang code. --spec scan_erl_exprs(prompt()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_exprs(Prompt) -> Result when + Prompt :: prompt(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_exprs(Prompt) -> scan_erl_exprs(default_input(), Prompt, 1). --spec scan_erl_exprs(device(), prompt()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_exprs(Device, Prompt) -> Result when + Device :: device(), + Prompt :: prompt(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_exprs(Io, Prompt) -> scan_erl_exprs(Io, Prompt, 1). --spec scan_erl_exprs(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_exprs(Device, Prompt, StartLine) -> Result when + Device :: device(), + Prompt :: prompt(), + StartLine :: line(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_exprs(Io, Prompt, Pos0) -> request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}). --spec scan_erl_form(prompt()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_form(Prompt) -> Result when + Prompt :: prompt(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_form(Prompt) -> scan_erl_form(default_input(), Prompt, 1). --spec scan_erl_form(device(), prompt()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_form(IoDevice, Prompt) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_form(Io, Prompt) -> scan_erl_form(Io, Prompt, 1). --spec scan_erl_form(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error(). +-spec scan_erl_form(IoDevice, Prompt, StartLine) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + StartLine :: line(), + Result :: erl_scan:tokens_result() | request_error(). scan_erl_form(Io, Prompt, Pos0) -> request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}). %% Parsing Erlang code. --type erl_parse_expr_list() :: [_]. %% XXX: should be imported from erl_parse - --type parse_ret() :: {'ok', erl_parse_expr_list(), line()} - | {'eof', line()} - | {'error', erl_scan:error_info(), line()} +-type parse_ret() :: {'ok', ExprList :: erl_parse:abstract_expr(), EndLine :: line()} + | {'eof', EndLine :: line()} + | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()} | request_error(). --spec parse_erl_exprs(prompt()) -> parse_ret(). +-spec parse_erl_exprs(Prompt) -> Result when + Prompt :: prompt(), + Result :: parse_ret(). parse_erl_exprs(Prompt) -> parse_erl_exprs(default_input(), Prompt, 1). --spec parse_erl_exprs(device(), prompt()) -> parse_ret(). +-spec parse_erl_exprs(IoDevice, Prompt) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + Result :: parse_ret(). parse_erl_exprs(Io, Prompt) -> parse_erl_exprs(Io, Prompt, 1). --spec parse_erl_exprs(device(), prompt(), line()) -> parse_ret(). +-spec parse_erl_exprs(IoDevice, Prompt, StartLine) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + StartLine :: line(), + Result :: parse_ret(). parse_erl_exprs(Io, Prompt, Pos0) -> case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of @@ -349,24 +433,31 @@ parse_erl_exprs(Io, Prompt, Pos0) -> Other end. --type erl_parse_absform() :: _. %% XXX: should be imported from erl_parse - --type parse_form_ret() :: {'ok', erl_parse_absform(), line()} - | {'eof', line()} - | {'error', erl_scan:error_info(), line()} +-type parse_form_ret() :: {'ok', AbsForm :: erl_parse:abstract_form(), EndLine :: line()} + | {'eof', EndLine :: line()} + | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()} | request_error(). --spec parse_erl_form(prompt()) -> parse_form_ret(). +-spec parse_erl_form(Prompt) -> Result when + Prompt :: prompt(), + Result :: parse_form_ret(). parse_erl_form(Prompt) -> parse_erl_form(default_input(), Prompt, 1). --spec parse_erl_form(device(), prompt()) -> parse_form_ret(). +-spec parse_erl_form(IoDevice, Prompt) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + Result :: parse_form_ret(). parse_erl_form(Io, Prompt) -> parse_erl_form(Io, Prompt, 1). --spec parse_erl_form(device(), prompt(), line()) -> parse_form_ret(). +-spec parse_erl_form(IoDevice, Prompt, StartLine) -> Result when + IoDevice :: device(), + Prompt :: prompt(), + StartLine :: line(), + Result :: parse_form_ret(). parse_erl_form(Io, Prompt, Pos0) -> case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index 4ca9d079b7..0252cdf742 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -75,35 +75,57 @@ collect_line/2, collect_line/3, collect_line/4, get_until/3, get_until/4]). --export_type([chars/0]). +-export_type([chars/0, continuation/0]). %%---------------------------------------------------------------------- - %% XXX: overapproximates a deep list of (unicode) characters --type chars() :: [_]. +-type chars() :: [char() | chars()]. -type depth() :: -1 | non_neg_integer(). +-opaque continuation() :: {_, _, _, _}. % XXX: refine + %%---------------------------------------------------------------------- %% Interface calls to sub-modules. --spec fwrite(io:format(), [term()]) -> chars(). +-spec fwrite(Format, Data) -> chars() | UnicodeList when + Format :: io:format(), + Data :: [term()], + UnicodeList :: [unicode:unicode_char()], + Data :: [term()]. fwrite(Format, Args) -> format(Format, Args). --spec fread(string(), string()) -> io_lib_fread:fread_2_ret(). +-spec fread(Format, String) -> Result when + Format :: string(), + String :: string(), + Result :: {'ok', InputList :: [term()], LeftOverChars :: string()} + | {'more', RestFormat :: string(), + Nchars :: non_neg_integer(), + InputStack :: chars()} + | {'error', What :: term()}. fread(Chars, Format) -> io_lib_fread:fread(Chars, Format). --spec fread(io_lib_fread:continuation(), string(), string()) -> - io_lib_fread:fread_3_ret(). +-spec fread(Continuation, CharSpec, Format) -> Return when + Continuation :: continuation() | [], + CharSpec :: string() | eof, + Format :: string(), + Return :: {'more', Continuation1 :: continuation()} + | {'done', Result, LeftOverChars :: string()}, + Result :: {'ok', InputList :: [term()]} + | 'eof' + | {'error', What :: term()}. fread(Cont, Chars, Format) -> io_lib_fread:fread(Cont, Chars, Format). --spec format(io:format(), [term()]) -> chars(). +-spec format(Format, Data) -> chars() | UnicodeList when + Format :: io:format(), + Data :: [term()], + UnicodeList :: [unicode:unicode_char()]. format(Format, Args) -> case catch io_lib_format:fwrite(Format, Args) of @@ -113,17 +135,24 @@ format(Format, Args) -> Other end. --spec print(term()) -> chars(). +-spec print(Term) -> chars() when + Term :: term(). print(Term) -> io_lib_pretty:print(Term). --spec print(term(), non_neg_integer(), non_neg_integer(), depth()) -> chars(). +-spec print(Term, Column, LineLength, Depth) -> chars() when + Term :: term(), + Column :: non_neg_integer(), + LineLength :: non_neg_integer(), + Depth :: depth(). print(Term, Column, LineLength, Depth) -> io_lib_pretty:print(Term, Column, LineLength, Depth). --spec indentation(string(), integer()) -> integer(). +-spec indentation(String, StartIndent) -> integer() when + String :: string(), + StartIndent :: integer(). indentation(Chars, Current) -> io_lib_format:indentation(Chars, Current). @@ -158,7 +187,8 @@ format_prompt(Format, Args) -> %% Return a (non-flattened) list of characters giving a printed %% representation of the term. write/3 is for backward compatibility. --spec write(term()) -> chars(). +-spec write(Term) -> chars() when + Term :: term(). write(Term) -> write(Term, -1). @@ -169,7 +199,9 @@ write(Term, D, true) -> write(Term, D, false) -> write(Term, D). --spec write(term(), depth()) -> chars(). +-spec write(Term, Depth) -> chars() when + Term :: term(), + Depth :: depth(). write(_Term, 0) -> "..."; write(Term, _D) when is_integer(Term) -> integer_to_list(Term); @@ -234,7 +266,8 @@ write_binary_body(B, _D) -> %% write_atom(Atom) -> [Char] %% Generate the list of characters needed to print an atom. --spec write_atom(atom()) -> chars(). +-spec write_atom(Atom) -> chars() when + Atom :: atom(). write_atom(Atom) -> Chars = atom_to_list(Atom), @@ -283,7 +316,8 @@ name_char(_) -> false. %% write_string([Char]) -> [Char] %% Generate the list of characters needed to print a string. --spec write_string(string()) -> chars(). +-spec write_string(String) -> chars() when + String :: string(). write_string(S) -> write_string(S, $"). %" @@ -330,7 +364,8 @@ string_char(_,C, _, Tail) when C < $\240-> %Other control characters. %% Generate the list of characters needed to print a character constant. %% Must special case SPACE, $\s, here. --spec write_char(char()) -> chars(). +-spec write_char(Char) -> chars() when + Char :: char(). write_char($\s) -> "$\\s"; %Must special case this. write_char(C) when is_integer(C), C >= $\000, C =< $\377 -> @@ -346,7 +381,8 @@ write_unicode_char(Uni) -> %% Return true if CharList is a (possibly deep) list of characters, else %% false. --spec char_list(term()) -> boolean(). +-spec char_list(Term) -> boolean() when + Term :: term(). char_list([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> char_list(Cs); @@ -362,7 +398,8 @@ unicode_char_list([C|Cs]) when is_integer(C), C >= 0, C < 16#D800; unicode_char_list([]) -> true; unicode_char_list(_) -> false. %Everything else is false --spec deep_char_list(term()) -> boolean(). +-spec deep_char_list(Term) -> boolean() when + Term :: term(). deep_char_list(Cs) -> deep_char_list(Cs, []). @@ -399,7 +436,8 @@ deep_unicode_char_list(_, _More) -> %Everything else is false %% Return true if CharList is a list of printable characters, else %% false. --spec printable_list(term()) -> boolean(). +-spec printable_list(Term) -> boolean() when + Term :: term(). printable_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 -> printable_list(Cs); diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl index 33553692bc..ded1346097 100644 --- a/lib/stdlib/src/io_lib_fread.erl +++ b/lib/stdlib/src/io_lib_fread.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -22,27 +22,11 @@ -export([fread/2,fread/3]). --export_type([continuation/0, fread_2_ret/0, fread_3_ret/0]). - -import(lists, [reverse/1,reverse/2]). -%%----------------------------------------------------------------------- -%% Local types -%%----------------------------------------------------------------------- - --type done_arg2() :: {'ok', io_lib:chars()} | 'eof' | {'error', term()}. - -%%----------------------------------------------------------------------- -%% Types also used in other files -%%----------------------------------------------------------------------- - --type continuation() :: [] | {_, _, _, _}. % XXX: refine - --type fread_2_ret() :: {'ok', io_lib:chars(), string()} - | {'more', string(), non_neg_integer(), io_lib:chars()} - | {'error', term()}. --type fread_3_ret() :: {'more', continuation()} - | {'done', done_arg2(), string()}. +-define(is_whitespace(C), + ((C) =:= $\s orelse (C) =:= $\t + orelse (C) =:= $\r orelse (C) =:= $\n)). %%----------------------------------------------------------------------- @@ -51,7 +35,15 @@ %% repeatedly collects lines and calls fread/2 to format the input until %% all the format string has been used. And it counts the characters. --spec fread(io_lib_fread:continuation(), string(), string()) -> fread_3_ret(). +-spec fread(Continuation, String, Format) -> Return when + Continuation :: io_lib:continuation() | [], + String :: string(), + Format :: string(), + Return :: {'more', Continuation1 :: io_lib:continuation()} + | {'done', Result, LeftOverChars :: string()}, + Result :: {'ok', InputList :: io_lib:chars()} + | 'eof' + | {'error', What :: term()}. fread([], Chars, Format) -> %%io:format("FREAD: ~w `~s'~n", [Format,Chars]), @@ -106,36 +98,39 @@ fread_line(Format0, Line, N0, Results0, More, Newline) -> %% WHITE Skip white space %% X Literal X --spec fread(string(), string()) -> fread_2_ret(). +-spec fread(Format, String) -> Result when + Format :: string(), + String :: string(), + Result :: {'ok', InputList :: io_lib:chars(), LeftOverChars :: string()} + | {'more', RestFormat :: string(), + Nchars :: non_neg_integer(), + InputStack :: io_lib:chars()} + | {'error', What :: term()}. fread(Format, Line) -> fread(Format, Line, 0, []). -fread([$~|Format0], Line, N, Results) -> +fread([$~|Format0]=AllFormat, Line, N, Results) -> {Format,F,Sup,Unicode} = fread_field(Format0), - fread1(Format, F, Sup, Unicode, Line, N, Results, Format0); -fread([$\s|Format], Line, N, Results) -> - fread_skip_white(Format, Line, N, Results); -fread([$\t|Format], Line, N, Results) -> - fread_skip_white(Format, Line, N, Results); -fread([$\r|Format], Line, N, Results) -> - fread_skip_white(Format, Line, N, Results); -fread([$\n|Format], Line, N, Results) -> + fread1(Format, F, Sup, Unicode, Line, N, Results, AllFormat); +fread([C|Format], Line, N, Results) when ?is_whitespace(C) -> fread_skip_white(Format, Line, N, Results); fread([C|Format], [C|Line], N, Results) -> fread(Format, Line, N+1, Results); fread([_F|_Format], [_C|_Line], _N, _Results) -> fread_error(input); +fread([_|_]=Format, [], N, Results) -> + {more,Format,N,Results}; +fread([_|_], eof, 0, []) -> + %% This is at start of input so no error. + eof; +fread([_|_], eof, _N, _Results) -> + %% This is an error as there is no more input. + fread_error(input); fread([], Line, _N, Results) -> {ok,reverse(Results),Line}. -fread_skip_white(Format, [$\s|Line], N, Results) -> - fread_skip_white(Format, Line, N+1, Results); -fread_skip_white(Format, [$\t|Line], N, Results) -> - fread_skip_white(Format, Line, N+1, Results); -fread_skip_white(Format, [$\r|Line], N, Results) -> - fread_skip_white(Format, Line, N+1, Results); -fread_skip_white(Format, [$\n|Line], N, Results) -> +fread_skip_white(Format, [C|Line], N, Results) when ?is_whitespace(C) -> fread_skip_white(Format, Line, N+1, Results); fread_skip_white(Format, Line, N, Results) -> fread(Format, Line, N, Results). @@ -171,9 +166,9 @@ fread1([$l|Format], _F, Sup, _U, Line, N, Res, _AllFormat) -> fread(Format, Line, N, fread_result(Sup, N, Res)); fread1(_Format, _F, _Sup, _U, [], N, Res, AllFormat) -> %% Need more input here. - {more,[$~|AllFormat],N,Res}; -fread1(_Format, _F, _Sup, _U, eof, _N, [], _AllFormat) -> - %% This is at start of format string so no error. + {more,AllFormat,N,Res}; +fread1(_Format, _F, _Sup, _U, eof, 0, [], _AllFormat) -> + %% This is at start of input so no error. eof; fread1(_Format, _F, _Sup, _U, eof, _N, _Res, _AllFormat) -> %% This is an error as there is no more input. @@ -391,26 +386,16 @@ fread_string_cs(Line0, N0, true) -> %% fread_digits(Line, N, Base, Characters) %% Read segments of things, return "thing" characters in reverse order. -fread_skip_white([$\s|Line]) -> fread_skip_white(Line); -fread_skip_white([$\t|Line]) -> fread_skip_white(Line); -fread_skip_white([$\r|Line]) -> fread_skip_white(Line); -fread_skip_white([$\n|Line]) -> fread_skip_white(Line); +fread_skip_white([C|Line]) when ?is_whitespace(C) -> + fread_skip_white(Line); fread_skip_white(Line) -> Line. -fread_skip_white([$\s|Line], N) -> - fread_skip_white(Line, N+1); -fread_skip_white([$\t|Line], N) -> - fread_skip_white(Line, N+1); -fread_skip_white([$\r|Line], N) -> - fread_skip_white(Line, N+1); -fread_skip_white([$\n|Line], N) -> +fread_skip_white([C|Line], N) when ?is_whitespace(C) -> fread_skip_white(Line, N+1); fread_skip_white(Line, N) -> {Line,N}. -fread_skip_latin1_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs}; -fread_skip_latin1_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs}; -fread_skip_latin1_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs}; -fread_skip_latin1_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs}; +fread_skip_latin1_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) -> + {[C|Line],N,Cs}; fread_skip_latin1_nonwhite([C|Line], N, []) when C > 255 -> {[C|Line],N,error}; fread_skip_latin1_nonwhite([C|Line], N, Cs) when C > 255 -> @@ -419,10 +404,8 @@ fread_skip_latin1_nonwhite([C|Line], N, Cs) -> fread_skip_latin1_nonwhite(Line, N+1, [C|Cs]); fread_skip_latin1_nonwhite([], N, Cs) -> {[],N,Cs}. -fread_skip_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs}; -fread_skip_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs}; -fread_skip_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs}; -fread_skip_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs}; +fread_skip_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) -> + {[C|Line],N,Cs}; fread_skip_nonwhite([C|Line], N, Cs) -> fread_skip_nonwhite(Line, N+1, [C|Cs]); fread_skip_nonwhite([], N, Cs) -> {[],N,Cs}. diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl index b2cfb00de9..314fd60903 100644 --- a/lib/stdlib/src/lib.erl +++ b/lib/stdlib/src/lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -38,7 +38,9 @@ flush_receive() -> %% %% Functions for doing standard system format i/o. %% --spec error_message(atom() | string() | binary(), [term()]) -> 'ok'. +-spec error_message(Format, Args) -> 'ok' when + Format :: io:format(), + Args :: [term()]. error_message(Format, Args) -> io:format(<<"** ~s **\n">>, [io_lib:format(Format, Args)]). @@ -55,17 +57,23 @@ progname() -> no_prog_name end. --spec nonl(string()) -> string(). +-spec nonl(String1) -> String2 when + String1 :: string(), + String2 :: string(). nonl([10]) -> []; nonl([]) -> []; nonl([H|T]) -> [H|nonl(T)]. --spec send(pid() | atom() | {atom(), node()}, term()) -> term(). +-spec send(To, Msg) -> Msg when + To :: pid() | atom() | {atom(), node()}, + Msg :: term(). send(To, Msg) -> To ! Msg. --spec sendw(pid() | atom() | {atom(), node()}, term()) -> term(). +-spec sendw(To, Msg) -> Msg when + To :: pid() | atom() | {atom(), node()}, + Msg :: term(). sendw(To, Msg) -> To ! {self(), Msg}, @@ -89,7 +97,7 @@ eval_str(Str) when is_list(Str) -> true -> case erl_parse:parse_exprs(Toks) of {ok, Exprs} -> - case catch erl_eval:exprs(Exprs, []) of + case catch erl_eval:exprs(Exprs, erl_eval:new_bindings()) of {value, Val, _} -> {ok, Val}; Other -> @@ -165,12 +173,12 @@ format_fun(Fun) when is_function(Fun) -> analyze_exception(error, Term, Stack) -> case {is_stacktrace(Stack), Stack, Term} of - {true, [{_M,_F,As}=MFA|MFAs], function_clause} when is_list(As) -> - {Term,[MFA],MFAs}; - {true, [{shell,F,A}], function_clause} when is_integer(A) -> + {true, [{_,_,As,_}=MFAL|MFAs], function_clause} when is_list(As) -> + {Term,[MFAL],MFAs}; + {true, [{shell,F,A,_}], function_clause} when is_integer(A) -> {Term, [{F,A}], []}; - {true, [{_M,_F,_AorAs}=MFA|MFAs], undef} -> - {Term,[MFA],MFAs}; + {true, [{_,_,_,_}=MFAL|MFAs], undef} -> + {Term,[MFAL],MFAs}; {true, _, _} -> {Term,[],Stack}; {false, _, _} -> @@ -186,9 +194,11 @@ analyze_exception(_Class, Term, Stack) -> is_stacktrace([]) -> true; -is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) -> +is_stacktrace([{M,F,A,I}|Fs]) + when is_atom(M), is_atom(F), is_integer(A), is_list(I) -> is_stacktrace(Fs); -is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), length(As) >= 0 -> +is_stacktrace([{M,F,As,I}|Fs]) + when is_atom(M), is_atom(F), length(As) >= 0, is_list(I) -> is_stacktrace(Fs); is_stacktrace(_) -> false. @@ -217,9 +227,9 @@ explain_reason(function_clause, error, [{F,A}], _PF, _S) -> %% Shell commands FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]), [<<"no function clause matching call to ">> | FAs]; -explain_reason(function_clause, error=Cl, [{M,F,As}], PF, S) -> +explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S) -> Str = <<"no function clause matching ">>, - format_errstr_call(Str, Cl, {M,F}, As, PF, S); + [format_errstr_call(Str, Cl, {M,F}, As, PF, S),$\s|location(Loc)]; explain_reason(if_clause, error, [], _PF, _S) -> <<"no true branch found when evaluating an if expression">>; explain_reason(noproc, error, [], _PF, _S) -> @@ -234,11 +244,11 @@ explain_reason({try_clause,V}, error=Cl, [], PF, S) -> %% "there is no try clause with a true guard sequence and a %% pattern matching..." format_value(V, <<"no try clause matching ">>, Cl, PF, S); -explain_reason(undef, error, [{M,F,A}], _PF, _S) -> +explain_reason(undef, error, [{M,F,A,_}], _PF, _S) -> %% Only the arity is displayed, not the arguments, if there are any. io_lib:fwrite(<<"undefined function ~s">>, [mfa_to_string(M, F, n_args(A))]); -explain_reason({shell_undef,F,A}, error, [], _PF, _S) -> +explain_reason({shell_undef,F,A,_}, error, [], _PF, _S) -> %% Give nicer reports for undefined shell functions %% (but not when the user actively calls shell_default:F(...)). io_lib:fwrite(<<"undefined shell command ~s/~w">>, [F, n_args(A)]); @@ -284,17 +294,19 @@ argss(I) -> io_lib:fwrite(<<"~w arguments">>, [I]). format_stacktrace1(S0, Stack0, PF, SF) -> - Stack1 = lists:dropwhile(fun({M,F,A}) -> SF(M, F, A) + Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A) end, lists:reverse(Stack0)), S = [" " | S0], Stack = lists:reverse(Stack1), format_stacktrace2(S, Stack, 1, PF). -format_stacktrace2(S, [{M,F,A}|Fs], N, PF) when is_integer(A) -> - [io_lib:fwrite(<<"~s~s ~s">>, - [sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A)]) +format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF) when is_integer(A) -> + [io_lib:fwrite(<<"~s~s ~s ~s">>, + [sep(N, S), origin(N, M, F, A), + mfa_to_string(M, F, A), + location(L)]) | format_stacktrace2(S, Fs, N + 1, PF)]; -format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) -> +format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF) when is_list(As) -> A = length(As), CalledAs = [S,<<" called as ">>], C = format_call("", CalledAs, {M,F}, As, PF), @@ -305,6 +317,16 @@ format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) -> format_stacktrace2(_S, [], _N, _PF) -> "". +location(L) -> + File = proplists:get_value(file, L), + Line = proplists:get_value(line, L), + if + File =/= undefined, Line =/= undefined -> + io_lib:format("(~s, line ~w)", [File, Line]); + true -> + "" + end. + sep(1, S) -> S; sep(_, S) -> [$\n | S]. diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl index c669c1f7c1..e73c087753 100644 --- a/lib/stdlib/src/lists.erl +++ b/lib/stdlib/src/lists.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,13 +54,21 @@ %% append(X, Y) appends lists X and Y --spec append([T], [T]) -> [T]. +-spec append(List1, List2) -> List3 when + List1 :: [T], + List2 :: [T], + List3 :: [T], + T :: term(). append(L1, L2) -> L1 ++ L2. %% append(L) appends the list of lists L --spec append([[T]]) -> [T]. +-spec append(ListOfLists) -> List1 when + ListOfLists :: [List], + List :: [T], + List1 :: [T], + T :: term(). append([E]) -> E; append([H|T]) -> H ++ append(T); @@ -68,13 +76,20 @@ append([]) -> []. %% subtract(List1, List2) subtract elements in List2 form List1. --spec subtract([T], [T]) -> [T]. +-spec subtract(List1, List2) -> List3 when + List1 :: [T], + List2 :: [T], + List3 :: [T], + T :: term(). subtract(L1, L2) -> L1 -- L2. %% reverse(L) reverse all elements in the list L. Is now a BIF! --spec reverse([T]) -> [T]. +-spec reverse(List1) -> List2 when + List1 :: [T], + List2 :: [T], + T :: term(). reverse([] = L) -> L; @@ -93,13 +108,21 @@ reverse([A, B | L]) -> %% nth(N, L) returns the N`th element of the list L %% nthtail(N, L) returns the N`th tail of the list L --spec nth(pos_integer(), [T,...]) -> T. +-spec nth(N, List) -> Elem when + N :: pos_integer(), + List :: [T,...], + Elem :: T, + T :: term(). nth(1, [H|_]) -> H; nth(N, [_|T]) when N > 1 -> nth(N - 1, T). --spec nthtail(non_neg_integer(), [T,...]) -> [T]. +-spec nthtail(N, List) -> Tail when + N :: non_neg_integer(), + List :: [T,...], + Tail :: [T], + T :: term(). nthtail(1, [_|T]) -> T; nthtail(N, [_|T]) when N > 1 -> @@ -108,7 +131,10 @@ nthtail(0, L) when is_list(L) -> L. %% prefix(Prefix, List) -> (true | false) --spec prefix([T], [T]) -> boolean(). +-spec prefix(List1, List2) -> boolean() when + List1 :: [T], + List2 :: [T], + T :: term(). prefix([X|PreTail], [X|Tail]) -> prefix(PreTail, Tail); @@ -117,7 +143,10 @@ prefix([_|_], List) when is_list(List) -> false. %% suffix(Suffix, List) -> (true | false) --spec suffix([T], [T]) -> boolean(). +-spec suffix(List1, List2) -> boolean() when + List1 :: [T], + List2 :: [T], + T :: term(). suffix(Suffix, List) -> Delta = length(List) - length(Suffix), @@ -125,7 +154,10 @@ suffix(Suffix, List) -> %% last(List) returns the last element in a list. --spec last([T,...]) -> T. +-spec last(List) -> Last when + List :: [T,...], + Last :: T, + T :: term(). last([E|Es]) -> last(E, Es). @@ -137,7 +169,10 @@ last(E, []) -> E. %% returns the sequence Min..Max %% Min <= Max and Min and Max must be integers --spec seq(integer(), integer()) -> [integer()]. +-spec seq(From, To) -> Seq when + From :: integer(), + To :: integer(), + Seq :: [integer()]. seq(First, Last) when is_integer(First), is_integer(Last), First-1 =< Last -> @@ -152,7 +187,11 @@ seq_loop(1, X, L) -> seq_loop(0, _, L) -> L. --spec seq(integer(), integer(), integer()) -> [integer()]. +-spec seq(From, To, Incr) -> Seq when + From :: integer(), + To :: integer(), + Incr :: integer(), + Seq :: [integer()]. seq(First, Last, Inc) when is_integer(First), is_integer(Last), is_integer(Inc) -> @@ -178,7 +217,8 @@ seq_loop(0, _, _, L) -> %% sum(L) returns the sum of the elements in L --spec sum([number()]) -> number(). +-spec sum(List) -> number() when + List :: [number()]. sum(L) -> sum(L, 0). @@ -188,7 +228,11 @@ sum([], Sum) -> Sum. %% duplicate(N, X) -> [X,X,X,.....,X] (N times) %% return N copies of X --spec duplicate(non_neg_integer(), T) -> [T]. +-spec duplicate(N, Elem) -> List when + N :: non_neg_integer(), + Elem :: T, + List :: [T], + T :: term(). duplicate(N, X) when is_integer(N), N >= 0 -> duplicate(N, X, []). @@ -197,7 +241,10 @@ duplicate(N, X, L) -> duplicate(N-1, X, [X|L]). %% min(L) -> returns the minimum element of the list L --spec min([T,...]) -> T. +-spec min(List) -> Min when + List :: [T,...], + Min :: T, + T :: term(). min([H|T]) -> min(T, H). @@ -207,7 +254,10 @@ min([], Min) -> Min. %% max(L) -> returns the maximum element of the list L --spec max([T,...]) -> T. +-spec max(List) -> Max when + List :: [T,...], + Max :: T, + T :: term(). max([H|T]) -> max(T, H). @@ -218,12 +268,21 @@ max([], Max) -> Max. %% sublist(List, Start, Length) %% Returns the sub-list starting at Start of length Length. --spec sublist([T], pos_integer(), non_neg_integer()) -> [T]. +-spec sublist(List1, Start, Len) -> List2 when + List1 :: [T], + List2 :: [T], + Start :: pos_integer(), + Len :: non_neg_integer(), + T :: term(). sublist(List, S, L) when is_integer(L), L >= 0 -> sublist(nthtail(S-1, List), L). --spec sublist([T], non_neg_integer()) -> [T]. +-spec sublist(List1, Len) -> List2 when + List1 :: [T], + List2 :: [T], + Len :: non_neg_integer(), + T :: term(). sublist(List, L) when is_integer(L), is_list(List) -> sublist_2(List, L). @@ -238,7 +297,11 @@ sublist_2(List, L) when is_list(List), L > 0 -> %% delete(Item, List) -> List' %% Delete the first occurrence of Item from the list L. --spec delete(T, [T]) -> [T]. +-spec delete(Elem, List1) -> List2 when + Elem :: T, + List1 :: [T], + List2 :: [T], + T :: term(). delete(Item, [Item|Rest]) -> Rest; delete(Item, [H|Rest]) -> @@ -248,7 +311,12 @@ delete(_, []) -> []. %% Return [{X0, Y0}, {X1, Y1}, ..., {Xn, Yn}] for lists [X0, X1, ..., %% Xn] and [Y0, Y1, ..., Yn]. --spec zip([A], [B]) -> [{A, B}]. +-spec zip(List1, List2) -> List3 when + List1 :: [A], + List2 :: [B], + List3 :: [{A, B}], + A :: term(), + B :: term(). zip([X | Xs], [Y | Ys]) -> [{X, Y} | zip(Xs, Ys)]; zip([], []) -> []. @@ -256,7 +324,12 @@ zip([], []) -> []. %% Return {[X0, X1, ..., Xn], [Y0, Y1, ..., Yn]}, for a list [{X0, Y0}, %% {X1, Y1}, ..., {Xn, Yn}]. --spec unzip([{A, B}]) -> {[A], [B]}. +-spec unzip(List1) -> {List2, List3} when + List1 :: [{A, B}], + List2 :: [A], + List3 :: [B], + A :: term(), + B :: term(). unzip(Ts) -> unzip(Ts, [], []). @@ -266,7 +339,14 @@ unzip([], Xs, Ys) -> {reverse(Xs), reverse(Ys)}. %% Return [{X0, Y0, Z0}, {X1, Y1, Z1}, ..., {Xn, Yn, Zn}] for lists [X0, %% X1, ..., Xn], [Y0, Y1, ..., Yn] and [Z0, Z1, ..., Zn]. --spec zip3([A], [B], [C]) -> [{A, B, C}]. +-spec zip3(List1, List2, List3) -> List4 when + List1 :: [A], + List2 :: [B], + List3 :: [C], + List4 :: [{A, B, C}], + A :: term(), + B :: term(), + C :: term(). zip3([X | Xs], [Y | Ys], [Z | Zs]) -> [{X, Y, Z} | zip3(Xs, Ys, Zs)]; zip3([], [], []) -> []. @@ -274,7 +354,14 @@ zip3([], [], []) -> []. %% Return {[X0, X1, ..., Xn], [Y0, Y1, ..., Yn], [Z0, Z1, ..., Zn]}, for %% a list [{X0, Y0, Z0}, {X1, Y1, Z1}, ..., {Xn, Yn, Zn}]. --spec unzip3([{A, B, C}]) -> {[A], [B], [C]}. +-spec unzip3(List1) -> {List2, List3, List4} when + List1 :: [{A, B, C}], + List2 :: [A], + List3 :: [B], + List4 :: [C], + A :: term(), + B :: term(), + C :: term(). unzip3(Ts) -> unzip3(Ts, [], [], []). @@ -286,7 +373,14 @@ unzip3([], Xs, Ys, Zs) -> %% Return [F(X0, Y0), F(X1, Y1), ..., F(Xn, Yn)] for lists [X0, X1, ..., %% Xn] and [Y0, Y1, ..., Yn]. --spec zipwith(fun((X, Y) -> R), [X], [Y]) -> [R]. +-spec zipwith(Combine, List1, List2) -> List3 when + Combine :: fun((X, Y) -> T), + List1 :: [X], + List2 :: [Y], + List3 :: [T], + X :: term(), + Y :: term(), + T :: term(). zipwith(F, [X | Xs], [Y | Ys]) -> [F(X, Y) | zipwith(F, Xs, Ys)]; zipwith(F, [], []) when is_function(F, 2) -> []. @@ -294,7 +388,16 @@ zipwith(F, [], []) when is_function(F, 2) -> []. %% Return [F(X0, Y0, Z0), F(X1, Y1, Z1), ..., F(Xn, Yn, Zn)] for lists %% [X0, X1, ..., Xn], [Y0, Y1, ..., Yn] and [Z0, Z1, ..., Zn]. --spec zipwith3(fun((X, Y, Z) -> R), [X], [Y], [Z]) -> [R]. +-spec zipwith3(Combine, List1, List2, List3) -> List4 when + Combine :: fun((X, Y, Z) -> T), + List1 :: [X], + List2 :: [Y], + List3 :: [Z], + List4 :: [T], + X :: term(), + Y :: term(), + Z :: term(), + T :: term(). zipwith3(F, [X | Xs], [Y | Ys], [Z | Zs]) -> [F(X, Y, Z) | zipwith3(F, Xs, Ys, Zs)]; @@ -303,7 +406,10 @@ zipwith3(F, [], [], []) when is_function(F, 3) -> []. %% sort(List) -> L %% sorts the list L --spec sort([T]) -> [T]. +-spec sort(List1) -> List2 when + List1 :: [T], + List2 :: [T], + T :: term(). sort([X, Y | L] = L0) when X =< Y -> case L of @@ -350,7 +456,11 @@ sort_1(X, [], R) -> %% merge(List) -> L %% merges a list of sorted lists --spec merge([[T]]) -> [T]. +-spec merge(ListOfLists) -> List1 when + ListOfLists :: [List], + List :: [T], + List1 :: [T], + T :: term(). merge(L) -> mergel(L, []). @@ -358,7 +468,14 @@ merge(L) -> %% merge3(X, Y, Z) -> L %% merges three sorted lists X, Y and Z --spec merge3([X], [Y], [Z]) -> [(X | Y | Z)]. +-spec merge3(List1, List2, List3) -> List4 when + List1 :: [X], + List2 :: [Y], + List3 :: [Z], + List4 :: [(X | Y | Z)], + X :: term(), + Y :: term(), + Z :: term(). merge3(L1, [], L3) -> merge(L1, L3); @@ -382,7 +499,12 @@ rmerge3(L1, [H2 | T2], [H3 | T3]) -> %% merge(X, Y) -> L %% merges two sorted lists X and Y --spec merge([X], [Y]) -> [(X | Y)]. +-spec merge(List1, List2) -> List3 when + List1 :: [X], + List2 :: [Y], + List3 :: [(X | Y)], + X :: term(), + Y :: term(). merge(T1, []) -> T1; @@ -405,8 +527,9 @@ rmerge(T1, [H2 | T2]) -> %% in L - the elements in L can be atoms, numbers of strings. %% Returns a list of characters. --type concat_thing() :: atom() | integer() | float() | string(). --spec concat([concat_thing()]) -> string(). +-spec concat(Things) -> string() when + Things :: [Thing], + Thing :: atom() | integer() | float() | string(). concat(List) -> flatmap(fun thing_to_list/1, List). @@ -420,12 +543,17 @@ thing_to_list(X) when is_list(X) -> X. %Assumed to be a string %% flatten(List, Tail) %% Flatten a list, adding optional tail. --spec flatten([term()]) -> [term()]. +-spec flatten(DeepList) -> List when + DeepList :: [term() | DeepList], + List :: [term()]. flatten(List) when is_list(List) -> do_flatten(List, []). --spec flatten([term()], [term()]) -> [term()]. +-spec flatten(DeepList, Tail) -> List when + DeepList :: [term() | DeepList], + Tail :: [term()], + List :: [term()]. flatten(List, Tail) when is_list(List), is_list(Tail) -> do_flatten(List, Tail). @@ -440,7 +568,8 @@ do_flatten([], Tail) -> %% flatlength(List) %% Calculate the length of a list of lists. --spec flatlength([term()]) -> non_neg_integer(). +-spec flatlength(DeepList) -> non_neg_integer() when + DeepList :: [term() | DeepList]. flatlength(List) -> flatlength(List, 0). @@ -481,7 +610,12 @@ flatlength([], L) -> L. % keysearch3(Key, N, T); %keysearch3(Key, N, []) -> false. --spec keydelete(term(), pos_integer(), [T]) -> [T] when T :: tuple(). +-spec keydelete(Key, N, TupleList1) -> TupleList2 when + Key :: term(), + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple], + Tuple :: tuple(). keydelete(K, N, L) when is_integer(N), N > 0 -> keydelete3(K, N, L). @@ -491,7 +625,13 @@ keydelete3(Key, N, [H|T]) -> [H|keydelete3(Key, N, T)]; keydelete3(_, _, []) -> []. --spec keyreplace(term(), pos_integer(), [tuple()], tuple()) -> [tuple()]. +-spec keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2 when + Key :: term(), + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple], + NewTuple :: Tuple, + Tuple :: tuple(). keyreplace(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) -> keyreplace3(K, N, L, New). @@ -502,8 +642,12 @@ keyreplace3(Key, Pos, [H|T], New) -> [H|keyreplace3(Key, Pos, T, New)]; keyreplace3(_, _, [], _) -> []. --spec keytake(term(), pos_integer(), [tuple()]) -> - {'value', tuple(), [tuple()]} | 'false'. +-spec keytake(Key, N, TupleList1) -> {value, Tuple, TupleList2} | false when + Key :: term(), + N :: pos_integer(), + TupleList1 :: [tuple()], + TupleList2 :: [tuple()], + Tuple :: tuple(). keytake(Key, N, L) when is_integer(N), N > 0 -> keytake(Key, N, L, []). @@ -514,7 +658,13 @@ keytake(Key, N, [H|T], L) -> keytake(Key, N, T, [H|L]); keytake(_K, _N, [], _L) -> false. --spec keystore(term(), pos_integer(), [tuple()], tuple()) -> [tuple(),...]. +-spec keystore(Key, N, TupleList1, NewTuple) -> TupleList2 when + Key :: term(), + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple, ...], + NewTuple :: Tuple, + Tuple :: tuple(). keystore(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) -> keystore2(K, N, L, New). @@ -526,7 +676,11 @@ keystore2(Key, N, [H|T], New) -> keystore2(_Key, _N, [], New) -> [New]. --spec keysort(pos_integer(), [T]) -> [T] when T :: tuple(). +-spec keysort(N, TupleList1) -> TupleList2 when + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple], + Tuple :: tuple(). keysort(I, L) when is_integer(I), I > 0 -> case L of @@ -583,8 +737,14 @@ keysort_1(I, X, EX, [Y | L], R) -> keysort_1(_I, X, _EX, [], R) -> lists:reverse(R, [X]). --spec keymerge(pos_integer(), [X], [Y]) -> - [R] when X :: tuple(), Y :: tuple(), R :: tuple(). +-spec keymerge(N, TupleList1, TupleList2) -> TupleList3 when + N :: pos_integer(), + TupleList1 :: [T1], + TupleList2 :: [T2], + TupleList3 :: [(T1 | T2)], + T1 :: Tuple, + T2 :: Tuple, + Tuple :: tuple(). keymerge(Index, T1, L2) when is_integer(Index), Index > 0 -> case L2 of @@ -611,7 +771,11 @@ rkeymerge(Index, T1, L2) when is_integer(Index), Index > 0 -> lists:reverse(M, []) end. --spec ukeysort(pos_integer(), [T]) -> [T] when T :: tuple(). +-spec ukeysort(N, TupleList1) -> TupleList2 when + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple], + Tuple :: tuple(). ukeysort(I, L) when is_integer(I), I > 0 -> case L of @@ -676,8 +840,14 @@ ukeysort_1(I, X, EX, [Y | L]) -> ukeysort_1(_I, X, _EX, []) -> [X]. --spec ukeymerge(pos_integer(), [X], [Y]) -> - [(X | Y)] when X :: tuple(), Y :: tuple(). +-spec ukeymerge(N, TupleList1, TupleList2) -> TupleList3 when + N :: pos_integer(), + TupleList1 :: [T1], + TupleList2 :: [T2], + TupleList3 :: [(T1 | T2)], + T1 :: Tuple, + T2 :: Tuple, + Tuple :: tuple(). ukeymerge(Index, L1, T2) when is_integer(Index), Index > 0 -> case L1 of @@ -704,7 +874,12 @@ rukeymerge(Index, T1, L2) when is_integer(Index), Index > 0 -> lists:reverse(M, []) end. --spec keymap(fun((term()) -> term()), pos_integer(), [tuple()]) -> [tuple()]. +-spec keymap(Fun, N, TupleList1) -> TupleList2 when + Fun :: fun((Term1 :: term()) -> Term2 :: term()), + N :: pos_integer(), + TupleList1 :: [Tuple], + TupleList2 :: [Tuple], + Tuple :: tuple(). keymap(Fun, Index, [Tup|Tail]) -> [setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)]; @@ -713,7 +888,11 @@ keymap(Fun, Index, []) when is_integer(Index), Index >= 1, %%% Suggestion from OTP-2948: sort and merge with Fun. --spec sort(fun((T, T) -> boolean()), [T]) -> [T]. +-spec sort(Fun, List1) -> List2 when + Fun :: fun((A :: T, B :: T) -> boolean()), + List1 :: [T], + List2 :: [T], + T :: term(). sort(Fun, []) when is_function(Fun, 2) -> []; @@ -727,7 +906,13 @@ sort(Fun, [X, Y | T]) -> fsplit_2(Y, X, Fun, T, [], []) end. --spec merge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)]. +-spec merge(Fun, List1, List2) -> List3 when + Fun :: fun((A, B) -> boolean()), + List1 :: [A], + List2 :: [B], + List3 :: [(A | B)], + A :: term(), + B :: term(). merge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) -> lists:reverse(fmerge2_1(T1, H2, Fun, T2, []), []); @@ -743,7 +928,11 @@ rmerge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) -> rmerge(Fun, T1, []) when is_function(Fun, 2) -> T1. --spec usort(fun((T, T) -> boolean()), [T]) -> [T]. +-spec usort(Fun, List1) -> List2 when + Fun :: fun((T, T) -> boolean()), + List1 :: [T], + List2 :: [T], + T :: term(). usort(Fun, [_] = L) when is_function(Fun, 2) -> L; @@ -770,7 +959,13 @@ usort_1(Fun, X, [Y | L]) -> ufsplit_2(Y, L, Fun, [X]) end. --spec umerge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)]. +-spec umerge(Fun, List1, List2) -> List3 when + Fun :: fun((A, B) -> boolean()), + List1 :: [A], + List2 :: [B], + List3 :: [(A | B)], + A :: term(), + B :: term(). umerge(Fun, [], T2) when is_function(Fun, 2) -> T2; @@ -789,7 +984,10 @@ rumerge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) -> %% usort(List) -> L %% sorts the list L, removes duplicates --spec usort([T]) -> [T]. +-spec usort(List1) -> List2 when + List1 :: [T], + List2 :: [T], + T :: term(). usort([X, Y | L] = L0) when X < Y -> case L of @@ -844,7 +1042,11 @@ usort_1(X, []) -> %% umerge(List) -> L %% merges a list of sorted lists without duplicates, removes duplicates --spec umerge([[T]]) -> [T]. +-spec umerge(ListOfLists) -> List1 when + ListOfLists :: [List], + List :: [T], + List1 :: [T], + T :: term(). umerge(L) -> umergel(L). @@ -853,7 +1055,14 @@ umerge(L) -> %% merges three sorted lists X, Y and Z without duplicates, %% removes duplicates --spec umerge3([X], [Y], [Z]) -> [(X | Y | Z)]. +-spec umerge3(List1, List2, List3) -> List4 when + List1 :: [X], + List2 :: [Y], + List3 :: [Z], + List4 :: [(X | Y | Z)], + X :: term(), + Y :: term(), + Z :: term(). umerge3(L1, [], L3) -> umerge(L1, L3); @@ -878,7 +1087,12 @@ rumerge3(L1, [H2 | T2], [H3 | T3]) -> %% umerge(X, Y) -> L %% merges two sorted lists X and Y without duplicates, removes duplicates --spec umerge([X], [Y]) -> [(X | Y)]. +-spec umerge(List1, List2) -> List3 when + List1 :: [X], + List2 :: [Y], + List3 :: [(X | Y)], + X :: term(), + Y :: term(). umerge([], T2) -> T2; @@ -924,7 +1138,10 @@ rumerge(T1, [H2 | T2]) -> %% There are also versions with an extra argument, ExtraArgs, which is a %% list of extra arguments to each call. --spec all(fun((T) -> boolean()), [T]) -> boolean(). +-spec all(Pred, List) -> boolean() when + Pred :: fun((Elem :: T) -> boolean()), + List :: [T], + T :: term(). all(Pred, [Hd|Tail]) -> case Pred(Hd) of @@ -933,7 +1150,10 @@ all(Pred, [Hd|Tail]) -> end; all(Pred, []) when is_function(Pred, 1) -> true. --spec any(fun((T) -> boolean()), [T]) -> boolean(). +-spec any(Pred, List) -> boolean() when + Pred :: fun((Elem :: T) -> boolean()), + List :: [T], + T :: term(). any(Pred, [Hd|Tail]) -> case Pred(Hd) of @@ -942,31 +1162,59 @@ any(Pred, [Hd|Tail]) -> end; any(Pred, []) when is_function(Pred, 1) -> false. --spec map(fun((D) -> R), [D]) -> [R]. +-spec map(Fun, List1) -> List2 when + Fun :: fun((A) -> B), + List1 :: [A], + List2 :: [B], + A :: term(), + B :: term(). map(F, [H|T]) -> [F(H)|map(F, T)]; map(F, []) when is_function(F, 1) -> []. --spec flatmap(fun((D) -> [R]), [D]) -> [R]. +-spec flatmap(Fun, List1) -> List2 when + Fun :: fun((A) -> [B]), + List1 :: [A], + List2 :: [B], + A :: term(), + B :: term(). flatmap(F, [Hd|Tail]) -> F(Hd) ++ flatmap(F, Tail); flatmap(F, []) when is_function(F, 1) -> []. --spec foldl(fun((T, term()) -> term()), term(), [T]) -> term(). +-spec foldl(Fun, Acc0, List) -> Acc1 when + Fun :: fun((Elem :: T, AccIn) -> AccOut), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + List :: [T], + T :: term(). foldl(F, Accu, [Hd|Tail]) -> foldl(F, F(Hd, Accu), Tail); foldl(F, Accu, []) when is_function(F, 2) -> Accu. --spec foldr(fun((T, term()) -> term()), term(), [T]) -> term(). +-spec foldr(Fun, Acc0, List) -> Acc1 when + Fun :: fun((Elem :: T, AccIn) -> AccOut), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + List :: [T], + T :: term(). foldr(F, Accu, [Hd|Tail]) -> F(Hd, foldr(F, Accu, Tail)); foldr(F, Accu, []) when is_function(F, 2) -> Accu. --spec filter(Pred :: fun((T) -> boolean()), List :: [T]) -> [T]. +-spec filter(Pred, List1) -> List2 when + Pred :: fun((Elem :: T) -> boolean()), + List1 :: [T], + List2 :: [T], + T :: term(). filter(Pred, List) when is_function(Pred, 1) -> [ E || E <- List, Pred(E) ]. @@ -974,7 +1222,12 @@ filter(Pred, List) when is_function(Pred, 1) -> %% Equivalent to {filter(F, L), filter(NotF, L)}, if NotF = 'fun(X) -> %% not F(X) end'. --spec partition(Pred :: fun((T) -> boolean()), List :: [T]) -> {[T], [T]}. +-spec partition(Pred, List) -> {Satisfying, NotSatisfying} when + Pred :: fun((Elem :: T) -> boolean()), + List :: [T], + Satisfying :: [T], + NotSatisfying :: [T], + T :: term(). partition(Pred, L) -> partition(Pred, L, [], []). @@ -1000,14 +1253,26 @@ zf(F, [Hd|Tail]) -> end; zf(F, []) when is_function(F, 1) -> []. --spec foreach(F :: fun((T) -> term()), List :: [T]) -> 'ok'. +-spec foreach(Fun, List) -> ok when + Fun :: fun((Elem :: T) -> term()), + List :: [T], + T :: term(). foreach(F, [Hd|Tail]) -> F(Hd), foreach(F, Tail); foreach(F, []) when is_function(F, 1) -> ok. --spec mapfoldl(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}. +-spec mapfoldl(Fun, Acc0, List1) -> {List2, Acc1} when + Fun :: fun((A, AccIn) -> {B, AccOut}), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + List1 :: [A], + List2 :: [B], + A :: term(), + B :: term(). mapfoldl(F, Accu0, [Hd|Tail]) -> {R,Accu1} = F(Hd, Accu0), @@ -1015,7 +1280,16 @@ mapfoldl(F, Accu0, [Hd|Tail]) -> {[R|Rs],Accu2}; mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}. --spec mapfoldr(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}. +-spec mapfoldr(Fun, Acc0, List1) -> {List2, Acc1} when + Fun :: fun((A, AccIn) -> {B, AccOut}), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + List1 :: [A], + List2 :: [B], + A :: term(), + B :: term(). mapfoldr(F, Accu0, [Hd|Tail]) -> {Rs,Accu1} = mapfoldr(F, Accu0, Tail), @@ -1023,7 +1297,11 @@ mapfoldr(F, Accu0, [Hd|Tail]) -> {[R|Rs],Accu2}; mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}. --spec takewhile(fun((T) -> boolean()), [T]) -> [T]. +-spec takewhile(Pred, List1) -> List2 when + Pred :: fun((Elem :: T) -> boolean()), + List1 :: [T], + List2 :: [T], + T :: term(). takewhile(Pred, [Hd|Tail]) -> case Pred(Hd) of @@ -1032,7 +1310,11 @@ takewhile(Pred, [Hd|Tail]) -> end; takewhile(Pred, []) when is_function(Pred, 1) -> []. --spec dropwhile(fun((T) -> boolean()), [T]) -> [T]. +-spec dropwhile(Pred, List1) -> List2 when + Pred :: fun((Elem :: T) -> boolean()), + List1 :: [T], + List2 :: [T], + T :: term(). dropwhile(Pred, [Hd|Tail]=Rest) -> case Pred(Hd) of @@ -1041,7 +1323,12 @@ dropwhile(Pred, [Hd|Tail]=Rest) -> end; dropwhile(Pred, []) when is_function(Pred, 1) -> []. --spec splitwith(fun((T) -> boolean()), [T]) -> {[T], [T]}. +-spec splitwith(Pred, List) -> {List1, List2} when + Pred :: fun((T) -> boolean()), + List :: [T], + List1 :: [T], + List2 :: [T], + T :: term(). splitwith(Pred, List) when is_function(Pred, 1) -> splitwith(Pred, List, []). @@ -1054,7 +1341,12 @@ splitwith(Pred, [Hd|Tail], Taken) -> splitwith(Pred, [], Taken) when is_function(Pred, 1) -> {reverse(Taken),[]}. --spec split(non_neg_integer(), [T]) -> {[T], [T]}. +-spec split(N, List1) -> {List2, List3} when + N :: non_neg_integer(), + List1 :: [T], + List2 :: [T], + List3 :: [T], + T :: term(). split(N, List) when is_integer(N), N >= 0, is_list(List) -> case split(N, List, []) of diff --git a/lib/stdlib/src/log_mf_h.erl b/lib/stdlib/src/log_mf_h.erl index 5fa5360fa1..f7f128dac7 100644 --- a/lib/stdlib/src/log_mf_h.erl +++ b/lib/stdlib/src/log_mf_h.erl @@ -27,14 +27,13 @@ %%----------------------------------------------------------------- --type dir() :: file:filename(). -type b() :: non_neg_integer(). -type f() :: 1..255. -type pred() :: fun((term()) -> boolean()). %%----------------------------------------------------------------- --record(state, {dir :: dir(), +-record(state, {dir :: file:filename(), maxB :: b(), maxF :: f(), curB :: b(), @@ -67,11 +66,23 @@ %% EventMgr = pid() | atom(). %%----------------------------------------------------------------- --spec init(dir(), b(), f()) -> {dir(), b(), f(), pred()}. +-opaque args() :: {file:filename(), b(), f(), pred()}. + + +-spec init(Dir, MaxBytes, MaxFiles) -> Args when + Dir :: file:filename(), + MaxBytes :: non_neg_integer(), % b() + MaxFiles :: 1..255, % f() + Args :: args(). init(Dir, MaxB, MaxF) -> init(Dir, MaxB, MaxF, fun(_) -> true end). --spec init(dir(), b(), f(), pred()) -> {dir(), b(), f(), pred()}. +-spec init(Dir, MaxBytes, MaxFiles, Pred) -> Args when + Dir :: file:filename(), + MaxBytes :: non_neg_integer(), % b() + MaxFiles :: 1..255, % f() + Pred :: fun((Event :: term()) -> boolean()), % pred() + Args :: args(). init(Dir, MaxB, MaxF, Pred) -> {Dir, MaxB, MaxF, Pred}. @@ -79,7 +90,7 @@ init(Dir, MaxB, MaxF, Pred) -> {Dir, MaxB, MaxF, Pred}. %% Call-back functions from gen_event %%----------------------------------------------------------------- --spec init({dir(), b(), f(), pred()}) -> {'ok', #state{}} | {'error', term()}. +-spec init({file:filename(), non_neg_integer(), f(), pred()}) -> {'ok', #state{}} | {'error', term()}. init({Dir, MaxB, MaxF, Pred}) when is_integer(MaxF), MaxF > 0, MaxF < 256 -> First = diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index b565eb20f4..48e22e53fa 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -66,6 +66,11 @@ %% %% Called by compiler or ets/dbg:fun2ms when errors/warnings occur %% + +-spec(format_error(Error) -> Chars when + Error :: {error, module(), term()}, + Chars :: io_lib:chars()). + format_error({?WARN_SHADOW_VAR,Name}) -> lists:flatten( io_lib:format("variable ~p shadowed in ms_transform fun head", @@ -186,6 +191,12 @@ format_error(Else) -> %% %% Called when translating in shell %% + +-spec transform_from_shell(Dialect, Clauses, BoundEnvironment) -> term() when + Dialect :: ets | dbg, + Clauses :: [erl_parse:abstract_clause()], + BoundEnvironment :: erl_eval:binding_struct(). + transform_from_shell(Dialect, Clauses, BoundEnvironment) -> SaveFilename = setup_filename(), case catch ms_clause_list(1,Clauses,Dialect,gb_sets:new()) of @@ -211,6 +222,11 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) -> %% %% Called when translating during compiling %% + +-spec parse_transform(Forms, Options) -> Forms when + Forms :: [erl_parse:abstract_form()], + Options :: term(). + parse_transform(Forms, _Options) -> SaveFilename = setup_filename(), %io:format("Forms: ~p~n",[Forms]), diff --git a/lib/stdlib/src/orddict.erl b/lib/stdlib/src/orddict.erl index 4e30c9eefd..45d3c84b3e 100644 --- a/lib/stdlib/src/orddict.erl +++ b/lib/stdlib/src/orddict.erl @@ -25,9 +25,11 @@ -export([store/3,append/3,append_list/3,update/3,update/4,update_counter/3]). -export([fold/3,map/2,filter/2,merge/3]). +-export_type([orddict/0]). + %%--------------------------------------------------------------------------- --type orddict() :: [{term(), term()}]. +-type orddict() :: [{Key :: term(), Value :: term()}]. %%--------------------------------------------------------------------------- @@ -35,45 +37,63 @@ new() -> []. --spec is_key(Key::term(), Dictionary::orddict()) -> boolean(). +-spec is_key(Key, Orddict) -> boolean() when + Key :: term(), + Orddict :: orddict(). is_key(Key, [{K,_}|_]) when Key < K -> false; is_key(Key, [{K,_}|Dict]) when Key > K -> is_key(Key, Dict); is_key(_Key, [{_K,_Val}|_]) -> true; %Key == K is_key(_, []) -> false. --spec to_list(orddict()) -> [{term(), term()}]. +-spec to_list(Orddict) -> List when + Orddict :: orddict(), + List :: [{Key :: term(), Value :: term()}]. to_list(Dict) -> Dict. --spec from_list([{term(), term()}]) -> orddict(). +-spec from_list(List) -> Orddict when + List :: [{Key :: term(), Value :: term()}], + Orddict :: orddict(). from_list(Pairs) -> lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, [], Pairs). --spec size(orddict()) -> non_neg_integer(). +-spec size(Orddict) -> non_neg_integer() when + Orddict :: orddict(). size(D) -> length(D). --spec fetch(Key::term(), Dictionary::orddict()) -> term(). +-spec fetch(Key, Orddict) -> Value when + Key :: term(), + Value :: term(), + Orddict :: orddict(). fetch(Key, [{K,_}|D]) when Key > K -> fetch(Key, D); fetch(Key, [{K,Value}|_]) when Key == K -> Value. --spec find(Key::term(), Dictionary::orddict()) -> {'ok', term()} | 'error'. +-spec find(Key, Orddict) -> {'ok', Value} | 'error' when + Key :: term(), + Orddict :: orddict(), + Value :: term(). find(Key, [{K,_}|_]) when Key < K -> error; find(Key, [{K,_}|D]) when Key > K -> find(Key, D); find(_Key, [{_K,Value}|_]) -> {ok,Value}; %Key == K find(_, []) -> error. --spec fetch_keys(Dictionary::orddict()) -> [term()]. +-spec fetch_keys(Orddict) -> Keys when + Orddict :: orddict(), + Keys :: [term()]. fetch_keys([{Key,_}|Dict]) -> [Key|fetch_keys(Dict)]; fetch_keys([]) -> []. --spec erase(Key::term(), Dictionary::orddict()) -> orddict(). +-spec erase(Key, Orddict1) -> Orddict2 when + Key :: term(), + Orddict1 :: orddict(), + Orddict2 :: orddict(). erase(Key, [{K,_}=E|Dict]) when Key < K -> [E|Dict]; erase(Key, [{K,_}=E|Dict]) when Key > K -> @@ -81,7 +101,11 @@ erase(Key, [{K,_}=E|Dict]) when Key > K -> erase(_Key, [{_K,_Val}|Dict]) -> Dict; %Key == K erase(_, []) -> []. --spec store(Key::term(), Value::term(), Dictionary::orddict()) -> orddict(). +-spec store(Key, Value, Orddict1) -> Orddict2 when + Key :: term(), + Value :: term(), + Orddict1 :: orddict(), + Orddict2 :: orddict(). store(Key, New, [{K,_}=E|Dict]) when Key < K -> [{Key,New},E|Dict]; @@ -91,7 +115,11 @@ store(Key, New, [{_K,_Old}|Dict]) -> %Key == K [{Key,New}|Dict]; store(Key, New, []) -> [{Key,New}]. --spec append(Key::term(), Value::term(), Dictionary::orddict()) -> orddict(). +-spec append(Key, Value, Orddict1) -> Orddict2 when + Key :: term(), + Value :: term(), + Orddict1 :: orddict(), + Orddict2 :: orddict(). append(Key, New, [{K,_}=E|Dict]) when Key < K -> [{Key,[New]},E|Dict]; @@ -101,7 +129,11 @@ append(Key, New, [{_K,Old}|Dict]) -> %Key == K [{Key,Old ++ [New]}|Dict]; append(Key, New, []) -> [{Key,[New]}]. --spec append_list(Key::term(), ValueList::[term()], orddict()) -> orddict(). +-spec append_list(Key, ValList, Orddict1) -> Orddict2 when + Key :: term(), + ValList :: [Value :: term()], + Orddict1 :: orddict(), + Orddict2 :: orddict(). append_list(Key, NewList, [{K,_}=E|Dict]) when Key < K -> [{Key,NewList},E|Dict]; @@ -112,14 +144,23 @@ append_list(Key, NewList, [{_K,Old}|Dict]) -> %Key == K append_list(Key, NewList, []) -> [{Key,NewList}]. --spec update(Key::term(), Fun::fun((term()) -> term()), orddict()) -> orddict(). +-spec update(Key, Fun, Orddict1) -> Orddict2 when + Key :: term(), + Fun :: fun((Value1 :: term()) -> Value2 :: term()), + Orddict1 :: orddict(), + Orddict2 :: orddict(). update(Key, Fun, [{K,_}=E|Dict]) when Key > K -> [E|update(Key, Fun, Dict)]; update(Key, Fun, [{K,Val}|Dict]) when Key == K -> [{Key,Fun(Val)}|Dict]. --spec update(term(), fun((term()) -> term()), term(), orddict()) -> orddict(). +-spec update(Key, Fun, Initial, Orddict1) -> Orddict2 when + Key :: term(), + Initial :: term(), + Fun :: fun((Value1 :: term()) -> Value2 :: term()), + Orddict1 :: orddict(), + Orddict2 :: orddict(). update(Key, _, Init, [{K,_}=E|Dict]) when Key < K -> [{Key,Init},E|Dict]; @@ -129,7 +170,11 @@ update(Key, Fun, _Init, [{_K,Val}|Dict]) -> %Key == K [{Key,Fun(Val)}|Dict]; update(Key, _, Init, []) -> [{Key,Init}]. --spec update_counter(Key::term(), Incr::number(), orddict()) -> orddict(). +-spec update_counter(Key, Increment, Orddict1) -> Orddict2 when + Key :: term(), + Increment :: number(), + Orddict1 :: orddict(), + Orddict2 :: orddict(). update_counter(Key, Incr, [{K,_}=E|Dict]) when Key < K -> [{Key,Incr},E|Dict]; @@ -139,19 +184,29 @@ update_counter(Key, Incr, [{_K,Val}|Dict]) -> %Key == K [{Key,Val+Incr}|Dict]; update_counter(Key, Incr, []) -> [{Key,Incr}]. --spec fold(fun((term(),term(),term()) -> term()), term(), orddict()) -> term(). +-spec fold(Fun, Acc0, Orddict) -> Acc1 when + Fun :: fun((Key :: term(), Value :: term(), AccIn :: term()) -> AccOut :: term()), + Acc0 :: term(), + Acc1 :: term(), + Orddict :: orddict(). fold(F, Acc, [{Key,Val}|D]) -> fold(F, F(Key, Val, Acc), D); fold(F, Acc, []) when is_function(F, 3) -> Acc. --spec map(fun((term(), term()) -> term()), orddict()) -> orddict(). +-spec map(Fun, Orddict1) -> Orddict2 when + Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()), + Orddict1 :: orddict(), + Orddict2 :: orddict(). map(F, [{Key,Val}|D]) -> [{Key,F(Key, Val)}|map(F, D)]; map(F, []) when is_function(F, 2) -> []. --spec filter(fun((term(), term()) -> boolean()), orddict()) -> orddict(). +-spec filter(Pred, Orddict1) -> Orddict2 when + Pred :: fun((Key :: term(), Value :: term()) -> boolean()), + Orddict1 :: orddict(), + Orddict2 :: orddict(). filter(F, [{Key,Val}=E|D]) -> case F(Key, Val) of @@ -160,8 +215,11 @@ filter(F, [{Key,Val}=E|D]) -> end; filter(F, []) when is_function(F, 2) -> []. --spec merge(fun((term(), term(), term()) -> term()), orddict(), orddict()) -> - orddict(). +-spec merge(Fun, Orddict1, Orddict2) -> Orddict3 when + Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()), + Orddict1 :: orddict(), + Orddict2 :: orddict(), + Orddict3 :: orddict(). merge(F, [{K1,_}=E1|D1], [{K2,_}=E2|D2]) when K1 < K2 -> [E1|merge(F, D1, [E2|D2])]; diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl index 5a1c260703..4a8b1275b2 100644 --- a/lib/stdlib/src/ordsets.erl +++ b/lib/stdlib/src/ordsets.erl @@ -40,7 +40,8 @@ new() -> []. %% is_set(Term) -> boolean(). %% Return 'true' if Set is an ordered set of elements, else 'false'. --spec is_set(term()) -> boolean(). +-spec is_set(Ordset) -> boolean() when + Ordset :: term(). is_set([E|Es]) -> is_set(Es, E); is_set([]) -> true; @@ -54,21 +55,26 @@ is_set([], _) -> true. %% size(OrdSet) -> int(). %% Return the number of elements in OrdSet. --spec size(ordset(_)) -> non_neg_integer(). +-spec size(Ordset) -> non_neg_integer() when + Ordset :: ordset(_). size(S) -> length(S). %% to_list(OrdSet) -> [Elem]. %% Return the elements in OrdSet as a list. --spec to_list(ordset(T)) -> [T]. +-spec to_list(Ordset) -> List when + Ordset :: ordset(T), + List :: [T]. to_list(S) -> S. %% from_list([Elem]) -> Set. %% Build an ordered set from the elements in List. --spec from_list([T]) -> ordset(T). +-spec from_list(List) -> Ordset when + List :: [T], + Ordset :: ordset(T). from_list(L) -> lists:usort(L). @@ -76,7 +82,9 @@ from_list(L) -> %% is_element(Element, OrdSet) -> boolean(). %% Return 'true' if Element is an element of OrdSet, else 'false'. --spec is_element(term(), ordset(_)) -> boolean(). +-spec is_element(Element, Ordset) -> boolean() when + Element :: term(), + Ordset :: ordset(_). is_element(E, [H|Es]) when E > H -> is_element(E, Es); is_element(E, [H|_]) when E < H -> false; @@ -86,7 +94,12 @@ is_element(_, []) -> false. %% add_element(Element, OrdSet) -> OrdSet. %% Return OrdSet with Element inserted in it. --spec add_element(E, ordset(T)) -> [T | E,...]. +-spec add_element(Element, Ordset1) -> Ordset2 when + Element :: E, + Ordset1 :: ordset(T), + Ordset2 :: ordset(T | E). + +%-spec add_element(E, ordset(T)) -> [T | E,...]. add_element(E, [H|Es]) when E > H -> [H|add_element(E, Es)]; add_element(E, [H|_]=Set) when E < H -> [E|Set]; @@ -96,7 +109,10 @@ add_element(E, []) -> [E]. %% del_element(Element, OrdSet) -> OrdSet. %% Return OrdSet but with Element removed. --spec del_element(term(), ordset(T)) -> ordset(T). +-spec del_element(Element, Ordset1) -> Ordset2 when + Element :: term(), + Ordset1 :: ordset(T), + Ordset2 :: ordset(T). del_element(E, [H|Es]) when E > H -> [H|del_element(E, Es)]; del_element(E, [H|_]=Set) when E < H -> Set; @@ -106,7 +122,10 @@ del_element(_, []) -> []. %% union(OrdSet1, OrdSet2) -> OrdSet %% Return the union of OrdSet1 and OrdSet2. --spec union(ordset(T1), ordset(T2)) -> ordset(T1 | T2). +-spec union(Ordset1, Ordset2) -> Ordset3 when + Ordset1 :: ordset(T1), + Ordset2 :: ordset(T2), + Ordset3 :: ordset(T1 | T2). union([E1|Es1], [E2|_]=Set2) when E1 < E2 -> [E1|union(Es1, Set2)]; @@ -120,7 +139,9 @@ union(Es1, []) -> Es1. %% union([OrdSet]) -> OrdSet %% Return the union of the list of ordered sets. --spec union([ordset(T)]) -> ordset(T). +-spec union(OrdsetList) -> Ordset when + OrdsetList :: [ordset(T)], + Ordset :: ordset(T). union([S1,S2|Ss]) -> union1(union(S1, S2), Ss); @@ -133,7 +154,10 @@ union1(S1, []) -> S1. %% intersection(OrdSet1, OrdSet2) -> OrdSet. %% Return the intersection of OrdSet1 and OrdSet2. --spec intersection(ordset(_), ordset(_)) -> ordset(_). +-spec intersection(Ordset1, Ordset2) -> Ordset3 when + Ordset1 :: ordset(_), + Ordset2 :: ordset(_), + Ordset3 :: ordset(_). intersection([E1|Es1], [E2|_]=Set2) when E1 < E2 -> intersection(Es1, Set2); @@ -149,7 +173,9 @@ intersection(_, []) -> %% intersection([OrdSet]) -> OrdSet. %% Return the intersection of the list of ordered sets. --spec intersection([ordset(_),...]) -> ordset(_). +-spec intersection(OrdsetList) -> Ordset when + OrdsetList :: [ordset(_),...], + Ordset :: ordset(_). intersection([S1,S2|Ss]) -> intersection1(intersection(S1, S2), Ss); @@ -162,7 +188,9 @@ intersection1(S1, []) -> S1. %% is_disjoint(OrdSet1, OrdSet2) -> boolean(). %% Check whether OrdSet1 and OrdSet2 are disjoint. --spec is_disjoint(ordset(_), ordset(_)) -> boolean(). +-spec is_disjoint(Ordset1, Ordset2) -> boolean() when + Ordset1 :: ordset(_), + Ordset2 :: ordset(_). is_disjoint([E1|Es1], [E2|_]=Set2) when E1 < E2 -> is_disjoint(Es1, Set2); @@ -179,7 +207,10 @@ is_disjoint(_, []) -> %% Return all and only the elements of OrdSet1 which are not also in %% OrdSet2. --spec subtract(ordset(_), ordset(_)) -> ordset(_). +-spec subtract(Ordset1, Ordset2) -> Ordset3 when + Ordset1 :: ordset(_), + Ordset2 :: ordset(_), + Ordset3 :: ordset(_). subtract([E1|Es1], [E2|_]=Set2) when E1 < E2 -> [E1|subtract(Es1, Set2)]; @@ -194,7 +225,9 @@ subtract(Es1, []) -> Es1. %% Return 'true' when every element of OrdSet1 is also a member of %% OrdSet2, else 'false'. --spec is_subset(ordset(_), ordset(_)) -> boolean(). +-spec is_subset(Ordset1, Ordset2) -> boolean() when + Ordset1 :: ordset(_), + Ordset2 :: ordset(_). is_subset([E1|_], [E2|_]) when E1 < E2 -> %E1 not in Set2 false; @@ -208,7 +241,11 @@ is_subset(_, []) -> false. %% fold(Fun, Accumulator, OrdSet) -> Accumulator. %% Fold function Fun over all elements in OrdSet and return Accumulator. --spec fold(fun((T, term()) -> term()), term(), ordset(T)) -> term(). +-spec fold(Function, Acc0, Ordset) -> Acc1 when + Function :: fun((Element :: T, AccIn :: term()) -> AccOut :: term()), + Ordset :: ordset(T), + Acc0 :: term(), + Acc1 :: term(). fold(F, Acc, Set) -> lists:foldl(F, Acc, Set). @@ -216,7 +253,10 @@ fold(F, Acc, Set) -> %% filter(Fun, OrdSet) -> OrdSet. %% Filter OrdSet with Fun. --spec filter(fun((T) -> boolean()), ordset(T)) -> ordset(T). +-spec filter(Pred, Ordset1) -> Ordset2 when + Pred :: fun((Element :: T) -> boolean()), + Ordset1 :: ordset(T), + Ordset2 :: ordset(T). filter(F, Set) -> lists:filter(F, Set). diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 5c52dfcbf0..c1285dab60 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -180,6 +180,9 @@ obsolete_1(calendar, local_time_to_universal_time, 1) -> obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 -> {deprecated, {rpc, multi_server_call, A}}; + +%% *** SNMP *** + obsolete_1(snmp, N, A) -> case is_snmp_agent_function(N, A) of false -> @@ -189,9 +192,100 @@ obsolete_1(snmp, N, A) -> integer_to_list(A)++" instead"} end; +obsolete_1(snmpm, agent_info, 3) -> + {deprecated, {snmpm, agent_info, 2}, "R16B"}; +obsolete_1(snmpm, update_agent_info, 5) -> + {deprecated, {snmpm, update_agent_info, 4}, "R16B"}; +obsolete_1(snmpm, g, 3) -> + {deprecated, {snmpm, sync_get, 3}, "R16B"}; +obsolete_1(snmpm, g, 4) -> + {deprecated, {snmpm, sync_get, [3,4]}, "R16B"}; +obsolete_1(snmpm, g, 5) -> + {deprecated, {snmpm, sync_get, [4,5]}, "R16B"}; +obsolete_1(snmpm, g, 6) -> + {deprecated, {snmpm, sync_get, [5,6]}, "R16B"}; +obsolete_1(snmpm, g, 7) -> + {deprecated, {snmpm, sync_get, 6}, "R16B"}; +obsolete_1(snmpm, ag, 3) -> + {deprecated, {snmpm, async_get, 3}, "R16B"}; +obsolete_1(snmpm, ag, 4) -> + {deprecated, {snmpm, async_get, [3,4]}, "R16B"}; +obsolete_1(snmpm, ag, 5) -> + {deprecated, {snmpm, async_get, [4,5]}, "R16B"}; +obsolete_1(snmpm, ag, 6) -> + {deprecated, {snmpm, async_get, [5,6]}, "R16B"}; +obsolete_1(snmpm, ag, 7) -> + {deprecated, {snmpm, async_get, 6}, "R16B"}; +obsolete_1(snmpm, gn, 3) -> + {deprecated, {snmpm, sync_get_next, 3}, "R16B"}; +obsolete_1(snmpm, gn, 4) -> + {deprecated, {snmpm, sync_get_next, [3,4]}, "R16B"}; +obsolete_1(snmpm, gn, 5) -> + {deprecated, {snmpm, sync_get_next, [4,5]}, "R16B"}; +obsolete_1(snmpm, gn, 6) -> + {deprecated, {snmpm, sync_get_next, [5,6]}, "R16B"}; +obsolete_1(snmpm, gn, 7) -> + {deprecated, {snmpm, sync_get_next, 6}, "R16B"}; +obsolete_1(snmpm, agn, 3) -> + {deprecated, {snmpm, async_get_next, 3}, "R16B"}; +obsolete_1(snmpm, agn, 4) -> + {deprecated, {snmpm, async_get_next, [3,4]}, "R16B"}; +obsolete_1(snmpm, agn, 5) -> + {deprecated, {snmpm, async_get_next, [4,5]}, "R16B"}; +obsolete_1(snmpm, agn, 6) -> + {deprecated, {snmpm, async_get_next, [5,6]}, "R16B"}; +obsolete_1(snmpm, agn, 7) -> + {deprecated, {snmpm, async_get_next, 6}, "R16B"}; +obsolete_1(snmpm, s, 3) -> + {deprecated, {snmpm, sync_set, 3}, "R16B"}; +obsolete_1(snmpm, s, 4) -> + {deprecated, {snmpm, sync_set, [3,4]}, "R16B"}; +obsolete_1(snmpm, s, 5) -> + {deprecated, {snmpm, sync_set, [4,5]}, "R16B"}; +obsolete_1(snmpm, s, 6) -> + {deprecated, {snmpm, sync_set, [5,6]}, "R16B"}; +obsolete_1(snmpm, s, 7) -> + {deprecated, {snmpm, sync_set, 6}, "R16B"}; +obsolete_1(snmpm, as, 3) -> + {deprecated, {snmpm, async_set, 3}, "R16B"}; +obsolete_1(snmpm, as, 4) -> + {deprecated, {snmpm, async_set, [3,4]}, "R16B"}; +obsolete_1(snmpm, as, 5) -> + {deprecated, {snmpm, async_set, [4,5]}, "R16B"}; +obsolete_1(snmpm, as, 6) -> + {deprecated, {snmpm, async_set, [5,6]}, "R16B"}; +obsolete_1(snmpm, as, 7) -> + {deprecated, {snmpm, async_set, 6}, "R16B"}; +obsolete_1(snmpm, gb, 5) -> + {deprecated, {snmpm, sync_get_bulk, 5}, "R16B"}; +obsolete_1(snmpm, gb, 6) -> + {deprecated, {snmpm, sync_get_bulk, [5,6]}, "R16B"}; +obsolete_1(snmpm, gb, 7) -> + {deprecated, {snmpm, sync_get_bulk, [6,7]}, "R16B"}; +obsolete_1(snmpm, gb, 8) -> + {deprecated, {snmpm, sync_get_bulk, [7,8]}, "R16B"}; +obsolete_1(snmpm, gb, 9) -> + {deprecated, {snmpm, sync_get_bulk, 8}, "R16B"}; +obsolete_1(snmpm, agb, 5) -> + {deprecated, {snmpm, async_get_bulk, 5}, "R16B"}; +obsolete_1(snmpm, agb, 6) -> + {deprecated, {snmpm, async_get_bulk, [5,6]}, "R16B"}; +obsolete_1(snmpm, agb, 7) -> + {deprecated, {snmpm, async_get_bulk, [6,7]}, "R16B"}; +obsolete_1(snmpm, agb, 8) -> + {deprecated, {snmpm, async_get_bulk, [7,8]}, "R16B"}; +obsolete_1(snmpm, agb, 9) -> + {deprecated, {snmpm, async_get_bulk, 8}, "R16B"}; + + +%% *** MEGACO *** + obsolete_1(megaco, format_versions, 1) -> {deprecated, "Deprecated; use megaco:print_version_info/0,1 instead"}; + +%% *** OS-MON-MIB *** + obsolete_1(os_mon_mib, init, 1) -> {deprecated, {os_mon_mib, load, 1}}; obsolete_1(os_mon_mib, stop, 1) -> @@ -236,22 +330,22 @@ obsolete_1(erlang, fault, 2) -> obsolete_1(file, rawopen, 2) -> {removed, "deprecated (will be removed in R13B); use file:open/2 with the raw option"}; -obsolete_1(http, request, 1) -> {deprecated,{httpc,request,1},"R15B"}; -obsolete_1(http, request, 2) -> {deprecated,{httpc,request,2},"R15B"}; -obsolete_1(http, request, 4) -> {deprecated,{httpc,request,4},"R15B"}; -obsolete_1(http, request, 5) -> {deprecated,{httpc,request,5},"R15B"}; -obsolete_1(http, cancel_request, 1) -> {deprecated,{httpc,cancel_request,1},"R15B"}; -obsolete_1(http, cancel_request, 2) -> {deprecated,{httpc,cancel_request,2},"R15B"}; -obsolete_1(http, set_option, 2) -> {deprecated,{httpc,set_option,2},"R15B"}; -obsolete_1(http, set_option, 3) -> {deprecated,{httpc,set_option,3},"R15B"}; -obsolete_1(http, set_options, 1) -> {deprecated,{httpc,set_options,1},"R15B"}; -obsolete_1(http, set_options, 2) -> {deprecated,{httpc,set_options,2},"R15B"}; -obsolete_1(http, verify_cookies, 2) -> {deprecated,{httpc,verify_cookies,2},"R15B"}; -obsolete_1(http, verify_cookies, 3) -> {deprecated,{httpc,verify_cookies,3},"R15B"}; -obsolete_1(http, cookie_header, 1) -> {deprecated,{httpc,cookie_header,1},"R15B"}; -obsolete_1(http, cookie_header, 2) -> {deprecated,{httpc,cookie_header,2},"R15B"}; -obsolete_1(http, stream_next, 1) -> {deprecated,{httpc,stream_next,1},"R15B"}; -obsolete_1(http, default_profile, 0) -> {deprecated,{httpc,default_profile,0},"R15B"}; +obsolete_1(http, request, 1) -> {removed,{httpc,request,1},"R15B"}; +obsolete_1(http, request, 2) -> {removed,{httpc,request,2},"R15B"}; +obsolete_1(http, request, 4) -> {removed,{httpc,request,4},"R15B"}; +obsolete_1(http, request, 5) -> {removed,{httpc,request,5},"R15B"}; +obsolete_1(http, cancel_request, 1) -> {removed,{httpc,cancel_request,1},"R15B"}; +obsolete_1(http, cancel_request, 2) -> {removed,{httpc,cancel_request,2},"R15B"}; +obsolete_1(http, set_option, 2) -> {removed,{httpc,set_option,2},"R15B"}; +obsolete_1(http, set_option, 3) -> {removed,{httpc,set_option,3},"R15B"}; +obsolete_1(http, set_options, 1) -> {removed,{httpc,set_options,1},"R15B"}; +obsolete_1(http, set_options, 2) -> {removed,{httpc,set_options,2},"R15B"}; +obsolete_1(http, verify_cookies, 2) -> {removed,{httpc,store_cookies,2},"R15B"}; +obsolete_1(http, verify_cookies, 3) -> {removed,{httpc,store_cookies,3},"R15B"}; +obsolete_1(http, cookie_header, 1) -> {removed,{httpc,cookie_header,1},"R15B"}; +obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"}; +obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"}; +obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"}; obsolete_1(httpd, start, 0) -> {removed,{inets,start,[2,3]},"R14B"}; obsolete_1(httpd, start, 1) -> {removed,{inets,start,[2,3]},"R14B"}; @@ -355,7 +449,7 @@ obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 -> %% Added in R13B04. obsolete_1(erlang, concat_binary, 1) -> - {deprecated,{erlang,list_to_binary,1},"R15B"}; + {removed,{erlang,list_to_binary,1},"R15B"}; %% Added in R14A. obsolete_1(ssl, peercert, 2) -> @@ -367,6 +461,18 @@ obsolete_1(public_key, pem_to_der, 1) -> obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 -> {deprecated,{public_key,pem_entry_decode,1},"R15A"}; +%% Added in R14B03. +obsolete_1(docb_gen, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; +obsolete_1(docb_transform, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; +obsolete_1(docb_xml_check, _, _) -> + {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; + +%% Added in R15B +obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver -> + {deprecated,"deprecated (will be removed in R16A); has no effect as drivers are no longer used."}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/pg.erl b/lib/stdlib/src/pg.erl index 503654e706..ee177e4e0b 100644 --- a/lib/stdlib/src/pg.erl +++ b/lib/stdlib/src/pg.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -35,7 +35,9 @@ %% Create a brand new empty process group with the master residing %% at the local node --spec create(term()) -> 'ok' | {'error', term()}. +-spec create(PgName) -> 'ok' | {'error', Reason} when + PgName :: term(), + Reason :: 'already_created' | term(). create(PgName) -> catch begin check(PgName), @@ -46,7 +48,10 @@ create(PgName) -> %% Create a brand new empty process group with the master %% residing at Node --spec create(term(), node()) -> 'ok' | {'error', term()}. +-spec create(PgName, Node) -> 'ok' | {'error', Reason} when + PgName :: term(), + Node :: node(), + Reason :: 'already_created' | term(). create(PgName, Node) -> catch begin check(PgName), @@ -66,7 +71,10 @@ standby(_PgName, _Node) -> %% Tell process group PgName that Pid is a new member of the group %% synchronously return a list of all old members in the group --spec join(atom(), pid()) -> [pid()]. +-spec join(PgName, Pid) -> Members when + PgName :: term(), + Pid :: pid(), + Members :: [pid()]. join(PgName, Pid) when is_atom(PgName) -> global:send(PgName, {join,self(),Pid}), @@ -77,7 +85,9 @@ join(PgName, Pid) when is_atom(PgName) -> %% Multi cast Mess to all members in the group --spec send(atom() | pid(), term()) -> 'ok'. +-spec send(PgName, Msg) -> 'ok' when + PgName :: term(), + Msg :: term(). send(PgName, Mess) when is_atom(PgName) -> global:send(PgName, {send, self(), Mess}), @@ -89,7 +99,9 @@ send(Pg, Mess) when is_pid(Pg) -> %% multi cast a message to all members in the group but ourselves %% If we are a member --spec esend(atom() | pid(), term()) -> 'ok'. +-spec esend(PgName, Msg) -> 'ok' when + PgName :: term(), + Msg :: term(). esend(PgName, Mess) when is_atom(PgName) -> global:send(PgName, {esend,self(),Mess}), @@ -100,7 +112,9 @@ esend(Pg, Mess) when is_pid(Pg) -> %% Return the members of the group --spec members(atom() | pid()) -> [pid()]. +-spec members(PgName) -> Members when + PgName :: term(), + Members :: [pid()]. members(PgName) when is_atom(PgName) -> global:send(PgName, {self() ,members}), diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl index 7f5f23e26d..a5eb191ab2 100644 --- a/lib/stdlib/src/pool.erl +++ b/lib/stdlib/src/pool.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -52,11 +52,16 @@ %% Start up using the .hosts.erlang file --spec start(atom()) -> [node()]. +-spec start(Name) -> Nodes when + Name :: atom(), + Nodes :: [node()]. start(Name) -> start(Name,[]). --spec start(atom(), string()) -> [node()]. +-spec start(Name, Args) -> Nodes when + Name :: atom(), + Args :: string(), + Nodes :: [node()]. start(Name, Args) when is_atom(Name) -> gen_server:start({global, pool_master}, pool, [], []), Hosts = net_adm:host_file(), @@ -71,7 +76,8 @@ start(Name, Args) when is_atom(Name) -> get_nodes() -> get_elements(2, get_nodes_and_load()). --spec attach(node()) -> 'already_attached' | 'attached'. +-spec attach(Node) -> 'already_attached' | 'attached' when + Node :: node(). attach(Node) -> gen_server:call({global, pool_master}, {attach, Node}). @@ -82,11 +88,17 @@ get_nodes_and_load() -> get_node() -> gen_server:call({global, pool_master}, get_node). --spec pspawn(module(), atom(), [term()]) -> pid(). +-spec pspawn(Mod, Fun, Args) -> pid() when + Mod :: module(), + Fun :: atom(), + Args :: [term()]. pspawn(M, F, A) -> gen_server:call({global, pool_master}, {spawn, group_leader(), M, F, A}). --spec pspawn_link(module(), atom(), [term()]) -> pid(). +-spec pspawn_link(Mod, Fun, Args) -> pid() when + Mod :: module(), + Fun :: atom(), + Args :: [term()]. pspawn_link(M, F, A) -> P = pspawn(M, F, A), link(P), @@ -95,6 +107,9 @@ pspawn_link(M, F, A) -> start_nodes([], _, _) -> []; start_nodes([Host|Tail], Name, Args) -> case slave:start(Host, Name, Args) of + {error, {already_running, Node}} -> + io:format("Can't start node on host ~w due to ~w~n",[Host, {already_running, Node}]), + [Node | start_nodes(Tail, Name, Args)]; {error, R} -> io:format("Can't start node on host ~w due to ~w~n",[Host, R]), start_nodes(Tail, Name, Args); diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index 4fb64a3353..02bcbb5a60 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,77 +40,108 @@ -type priority_level() :: 'high' | 'low' | 'max' | 'normal'. -type spawn_option() :: 'link' + | 'monitor' | {'priority', priority_level()} | {'min_heap_size', non_neg_integer()} + | {'min_bin_vheap_size', non_neg_integer()} | {'fullsweep_after', non_neg_integer()}. --type dict_or_pid() :: pid() | [_] | {integer(), integer(), integer()}. +-type dict_or_pid() :: pid() + | (ProcInfo :: [_]) + | {X :: integer(), Y :: integer(), Z :: integer()}. %%----------------------------------------------------------------------------- --spec spawn(function()) -> pid(). +-spec spawn(Fun) -> pid() when + Fun :: function(). spawn(F) when is_function(F) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn(?MODULE, init_p, [Parent,Ancestors,F]). --spec spawn(atom(), atom(), [term()]) -> pid(). +-spec spawn(Module, Function, Args) -> pid() when + Module :: module(), + Function :: atom(), + Args :: [term()]. spawn(M,F,A) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn(?MODULE, init_p, [Parent,Ancestors,M,F,A]). --spec spawn_link(function()) -> pid(). +-spec spawn_link(Fun) -> pid() when + Fun :: function(). spawn_link(F) when is_function(F) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn_link(?MODULE, init_p, [Parent,Ancestors,F]). --spec spawn_link(atom(), atom(), [term()]) -> pid(). +-spec spawn_link(Module, Function, Args) -> pid() when + Module :: module(), + Function :: atom(), + Args :: [term()]. spawn_link(M,F,A) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn_link(?MODULE, init_p, [Parent,Ancestors,M,F,A]). --spec spawn(node(), function()) -> pid(). +-spec spawn(Node, Fun) -> pid() when + Node :: node(), + Fun :: function(). spawn(Node, F) when is_function(F) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn(Node, ?MODULE, init_p, [Parent,Ancestors,F]). --spec spawn(node(), atom(), atom(), [term()]) -> pid(). +-spec spawn(Node, Module, Function, Args) -> pid() when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()]. + spawn(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn(Node, ?MODULE, init_p, [Parent,Ancestors,M,F,A]). --spec spawn_link(node(), function()) -> pid(). +-spec spawn_link(Node, Fun) -> pid() when + Node :: node(), + Fun :: function(). spawn_link(Node, F) when is_function(F) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn_link(Node, ?MODULE, init_p, [Parent,Ancestors,F]). --spec spawn_link(node(), atom(), atom(), [term()]) -> pid(). +-spec spawn_link(Node, Module, Function, Args) -> pid() when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()]. spawn_link(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), Ancestors = get_ancestors(), erlang:spawn_link(Node, ?MODULE, init_p, [Parent,Ancestors,M,F,A]). --spec spawn_opt(function(), [spawn_option()]) -> pid(). +-spec spawn_opt(Fun, SpawnOpts) -> pid() when + Fun :: function(), + SpawnOpts :: [spawn_option()]. + spawn_opt(F, Opts) when is_function(F) -> Parent = get_my_name(), Ancestors = get_ancestors(), check_for_monitor(Opts), erlang:spawn_opt(?MODULE, init_p, [Parent,Ancestors,F],Opts). --spec spawn_opt(node(), function(), [spawn_option()]) -> pid(). +-spec spawn_opt(Node, Function, SpawnOpts) -> pid() when + Node :: node(), + Function :: function(), + SpawnOpts :: [spawn_option()]. spawn_opt(Node, F, Opts) when is_function(F) -> Parent = get_my_name(), @@ -118,7 +149,11 @@ spawn_opt(Node, F, Opts) when is_function(F) -> check_for_monitor(Opts), erlang:spawn_opt(Node, ?MODULE, init_p, [Parent,Ancestors,F], Opts). --spec spawn_opt(atom(), atom(), [term()], [spawn_option()]) -> pid(). +-spec spawn_opt(Module, Function, Args, SpawnOpts) -> pid() when + Module :: module(), + Function :: atom(), + Args :: [term()], + SpawnOpts :: [spawn_option()]. spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), @@ -126,7 +161,12 @@ spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> check_for_monitor(Opts), erlang:spawn_opt(?MODULE, init_p, [Parent,Ancestors,M,F,A], Opts). --spec spawn_opt(node(), atom(), atom(), [term()], [spawn_option()]) -> pid(). +-spec spawn_opt(Node, Module, Function, Args, SpawnOpts) -> pid() when + Node :: node(), + Module :: module(), + Function :: atom(), + Args :: [term()], + SpawnOpts :: [spawn_option()]. spawn_opt(Node, M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> Parent = get_my_name(), @@ -144,7 +184,10 @@ check_for_monitor(SpawnOpts) -> false end. --spec hibernate(module(), atom(), [term()]) -> no_return(). +-spec hibernate(Module, Function, Args) -> no_return() when + Module :: module(), + Function :: atom(), + Args :: [term()]. hibernate(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> erlang:hibernate(?MODULE, wake_up, [M, F, A]). @@ -210,35 +253,65 @@ exit_p(Class, Reason) -> exit(Reason) end. --spec start(atom(), atom(), [term()]) -> term(). +-spec start(Module, Function, Args) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Ret :: term() | {error, Reason :: term()}. start(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> start(M, F, A, infinity). --spec start(atom(), atom(), [term()], timeout()) -> term(). +-spec start(Module, Function, Args, Time) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Time :: timeout(), + Ret :: term() | {error, Reason :: term()}. start(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) -> Pid = ?MODULE:spawn(M, F, A), sync_wait(Pid, Timeout). --spec start(atom(), atom(), [term()], timeout(), [spawn_option()]) -> term(). +-spec start(Module, Function, Args, Time, SpawnOpts) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Time :: timeout(), + SpawnOpts :: [spawn_option()], + Ret :: term() | {error, Reason :: term()}. start(M, F, A, Timeout, SpawnOpts) when is_atom(M), is_atom(F), is_list(A) -> Pid = ?MODULE:spawn_opt(M, F, A, SpawnOpts), sync_wait(Pid, Timeout). --spec start_link(atom(), atom(), [term()]) -> term(). +-spec start_link(Module, Function, Args) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Ret :: term() | {error, Reason :: term()}. start_link(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> start_link(M, F, A, infinity). --spec start_link(atom(), atom(), [term()], timeout()) -> term(). +-spec start_link(Module, Function, Args, Time) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Time :: timeout(), + Ret :: term() | {error, Reason :: term()}. start_link(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) -> Pid = ?MODULE:spawn_link(M, F, A), sync_wait(Pid, Timeout). --spec start_link(atom(),atom(),[term()],timeout(),[spawn_option()]) -> term(). +-spec start_link(Module, Function, Args, Time, SpawnOpts) -> Ret when + Module :: module(), + Function :: atom(), + Args :: [term()], + Time :: timeout(), + SpawnOpts :: [spawn_option()], + Ret :: term() | {error, Reason :: term()}. start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) -> Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)), @@ -267,13 +340,17 @@ flush(Pid) -> true end. --spec init_ack(pid(), term()) -> 'ok'. +-spec init_ack(Parent, Ret) -> 'ok' when + Parent :: pid(), + Ret :: term(). init_ack(Parent, Return) -> Parent ! {ack, self(), Return}, ok. --spec init_ack(term()) -> 'ok'. +-spec init_ack(Ret) -> 'ok' when + Ret :: term(). + init_ack(Return) -> [Parent|_] = get('$ancestors'), init_ack(Parent, Return). @@ -282,7 +359,11 @@ init_ack(Return) -> %% Fetch the initial call of a proc_lib spawned process. %% ----------------------------------------------------- --spec initial_call(dict_or_pid()) -> {atom(), atom(), [atom()]} | 'false'. +-spec initial_call(Process) -> {Module, Function, Args} | 'false' when + Process :: dict_or_pid(), + Module :: module(), + Function :: atom(), + Args :: [atom()]. initial_call(DictOrPid) -> case raw_initial_call(DictOrPid) of @@ -305,7 +386,11 @@ make_dummy_args(N, Acc) -> %% This function is typically called from c:i() and c:regs(). %% ----------------------------------------------------- --spec translate_initial_call(dict_or_pid()) -> mfa(). +-spec translate_initial_call(Process) -> {Module, Function, Arity} when + Process :: dict_or_pid(), + Module :: module(), + Function :: atom(), + Arity :: byte(). translate_initial_call(DictOrPid) -> case raw_initial_call(DictOrPid) of @@ -577,7 +662,8 @@ check(Res) -> Res. %%% Format (and write) a generated crash info structure. %%% ----------------------------------------------------------- --spec format([term()]) -> string(). +-spec format(CrashReport) -> string() when + CrashReport :: [term()]. format([OwnReport,LinkReport]) -> OwnFormat = format_report(OwnReport), diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl index 6a45e0f868..e3eda5d932 100644 --- a/lib/stdlib/src/proplists.erl +++ b/lib/stdlib/src/proplists.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ %% overriding the default settings, object properties, annotations, %% etc.</p> %% -%% @type property() = atom() | tuple() +%% % @type property() = atom() | tuple() -module(proplists). @@ -49,18 +49,13 @@ %% --------------------------------------------------------------------- --export_type([property/0]). +-export_type([property/0, proplist/0]). -type property() :: atom() | tuple(). - --type aliases() :: [{any(), any()}]. --type negations() :: [{any(), any()}]. --type expansions() :: [{property(), [any()]}]. +-type proplist() :: [property()]. %% --------------------------------------------------------------------- -%% @spec property(P::property()) -> property() -%% %% @doc Creates a normal form (minimal) representation of a property. If %% <code>P</code> is <code>{Key, true}</code> where <code>Key</code> is %% an atom, this returns <code>Key</code>, otherwise the whole term @@ -68,7 +63,8 @@ %% %% @see property/2 --spec property(property()) -> property(). +-spec property(Property) -> Property when + Property :: property(). property({Key, true}) when is_atom(Key) -> Key; @@ -76,8 +72,6 @@ property(Property) -> Property. -%% @spec property(Key::term(), Value::term()) -> property() -%% %% @doc Creates a normal form (minimal) representation of a simple %% key/value property. Returns <code>Key</code> if <code>Value</code> is %% <code>true</code> and <code>Key</code> is an atom, otherwise a tuple @@ -85,7 +79,10 @@ property(Property) -> %% %% @see property/1 --spec property(Key::term(), Value::term()) -> atom() | {term(), term()}. +-spec property(Key, Value) -> Property when + Key :: term(), + Value :: term(), + Property :: atom() | {term(), term()}. property(Key, true) when is_atom(Key) -> Key; @@ -95,14 +92,13 @@ property(Key, Value) -> %% --------------------------------------------------------------------- -%% @spec unfold(List::[term()]) -> [term()] -%% %% @doc Unfolds all occurences of atoms in <code>List</code> to tuples %% <code>{Atom, true}</code>. %% %% @see compact/1 --spec unfold(List::[term()]) -> [term()]. +-spec unfold(List) -> List when + List :: [term()]. unfold([P | Ps]) -> if is_atom(P) -> @@ -113,15 +109,14 @@ unfold([P | Ps]) -> unfold([]) -> []. -%% @spec compact(List::[term()]) -> [term()] -%% %% @doc Minimizes the representation of all entries in the list. This is %% equivalent to <code>[property(P) || P <- List]</code>. %% %% @see unfold/1 %% @see property/1 --spec compact(List::[property()]) -> [property()]. +-spec compact(List) -> List when + List :: [property()]. compact(List) -> [property(P) || P <- List]. @@ -129,8 +124,6 @@ compact(List) -> %% --------------------------------------------------------------------- -%% @spec lookup(Key::term(), List::[term()]) -> none | tuple() -%% %% @doc Returns the first entry associated with <code>Key</code> in %% <code>List</code>, if one exists, otherwise returns %% <code>none</code>. For an atom <code>A</code> in the list, the tuple @@ -140,7 +133,9 @@ compact(List) -> %% @see get_value/2 %% @see get_bool/2 --spec lookup(Key::term(), List::[term()]) -> 'none' | tuple(). +-spec lookup(Key, List) -> 'none' | tuple() when + Key :: term(), + List :: [term()]. lookup(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -154,15 +149,15 @@ lookup(Key, [P | Ps]) -> lookup(_Key, []) -> none. -%% @spec lookup_all(Key::term(), List::[term()]) -> [tuple()] -%% %% @doc Returns the list of all entries associated with <code>Key</code> %% in <code>List</code>. If no such entry exists, the result is the %% empty list. %% %% @see lookup/2 --spec lookup_all(Key::term(), List::[term()]) -> [tuple()]. +-spec lookup_all(Key, List) -> [tuple()] when + Key :: term(), + List :: [term()]. lookup_all(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -178,13 +173,13 @@ lookup_all(_Key, []) -> %% --------------------------------------------------------------------- -%% @spec is_defined(Key::term(), List::[term()]) -> boolean() -%% %% @doc Returns <code>true</code> if <code>List</code> contains at least %% one entry associated with <code>Key</code>, otherwise %% <code>false</code> is returned. --spec is_defined(Key::term(), List::[term()]) -> boolean(). +-spec is_defined(Key, List) -> boolean() when + Key :: term(), + List :: [term()]. is_defined(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -200,17 +195,15 @@ is_defined(_Key, []) -> %% --------------------------------------------------------------------- -%% @spec get_value(Key::term(), List::[term()]) -> term() %% @equiv get_value(Key, List, undefined) --spec get_value(Key::term(), List::[term()]) -> term(). +-spec get_value(Key, List) -> term() when + Key :: term(), + List :: List::[term()]. get_value(Key, List) -> get_value(Key, List, undefined). -%% @spec get_value(Key::term(), List::[term()], Default::term()) -> -%% term() -%% %% @doc Returns the value of a simple key/value property in %% <code>List</code>. If <code>lookup(Key, List)</code> would yield %% <code>{Key, Value}</code>, this function returns the corresponding @@ -221,7 +214,10 @@ get_value(Key, List) -> %% @see get_all_values/2 %% @see get_bool/2 --spec get_value(Key::term(), List::[term()], Default::term()) -> term(). +-spec get_value(Key, List, Default) -> term() when + Key :: term(), + List :: [term()], + Default :: term(). get_value(Key, [P | Ps], Default) -> if is_atom(P), P =:= Key -> @@ -240,8 +236,6 @@ get_value(Key, [P | Ps], Default) -> get_value(_Key, [], Default) -> Default. -%% @spec get_all_values(Key, List) -> [term()] -%% %% @doc Similar to <code>get_value/2</code>, but returns the list of %% values for <em>all</em> entries <code>{Key, Value}</code> in %% <code>List</code>. If no such entry exists, the result is the empty @@ -249,7 +243,9 @@ get_value(_Key, [], Default) -> %% %% @see get_value/2 --spec get_all_values(Key::term(), List::[term()]) -> [term()]. +-spec get_all_values(Key, List) -> [term()] when + Key :: term(), + List :: [term()]. get_all_values(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -267,8 +263,6 @@ get_all_values(Key, [P | Ps]) -> get_all_values(_Key, []) -> []. -%% @spec append_values(Key::term(), List::[term()]) -> [term()] -%% %% @doc Similar to <code>get_all_values/2</code>, but each value is %% wrapped in a list unless it is already itself a list, and the %% resulting list of lists is concatenated. This is often useful for @@ -278,7 +272,9 @@ get_all_values(_Key, []) -> %% %% @see get_all_values/2 --spec append_values(Key::term(), List::[term()]) -> [term()]. +-spec append_values(Key, List) -> List when + Key :: term(), + List :: [term()]. append_values(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -301,8 +297,6 @@ append_values(_Key, []) -> %% --------------------------------------------------------------------- -%% @spec get_bool(Key::term(), List::[term()]) -> boolean() -%% %% @doc Returns the value of a boolean key/value option. If %% <code>lookup(Key, List)</code> would yield <code>{Key, true}</code>, %% this function returns <code>true</code>; otherwise <code>false</code> @@ -311,7 +305,9 @@ append_values(_Key, []) -> %% @see lookup/2 %% @see get_value/2 --spec get_bool(Key::term(), List::[term()]) -> boolean(). +-spec get_bool(Key, List) -> boolean() when + Key :: term(), + List :: [term()]. get_bool(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -333,12 +329,11 @@ get_bool(_Key, []) -> %% --------------------------------------------------------------------- -%% @spec get_keys(List::[term()]) -> [term()] -%% %% @doc Returns an unordered list of the keys used in <code>List</code>, %% not containing duplicates. --spec get_keys(List::[term()]) -> [term()]. +-spec get_keys(List) -> [term()] when + List :: [term()]. get_keys(Ps) -> sets:to_list(get_keys(Ps, sets:new())). @@ -357,12 +352,12 @@ get_keys([], Keys) -> %% --------------------------------------------------------------------- -%% @spec delete(Key::term(), List::[term()]) -> [term()] -%% %% @doc Deletes all entries associated with <code>Key</code> from %% <code>List</code>. --spec delete(Key::term(), List::[term()]) -> [term()]. +-spec delete(Key, List) -> List when + Key :: term(), + List::[term()]. delete(Key, [P | Ps]) -> if is_atom(P), P =:= Key -> @@ -378,11 +373,6 @@ delete(_, []) -> %% --------------------------------------------------------------------- -%% @spec substitute_aliases(Aliases, List::[term()]) -> [term()] -%% -%% Aliases = [{Key, Key}] -%% Key = term() -%% %% @doc Substitutes keys of properties. For each entry in %% <code>List</code>, if it is associated with some key <code>K1</code> %% such that <code>{K1, K2}</code> occurs in <code>Aliases</code>, the @@ -398,7 +388,10 @@ delete(_, []) -> %% @see substitute_negations/2 %% @see normalize/2 --spec substitute_aliases(aliases(), List::[term()]) -> [term()]. +-spec substitute_aliases(Aliases, List) -> List when + Aliases :: [{Key, Key}], + Key :: term(), + List::[term()]. substitute_aliases(As, Props) -> [substitute_aliases_1(As, P) || P <- Props]. @@ -417,11 +410,6 @@ substitute_aliases_1([], P) -> %% --------------------------------------------------------------------- -%% @spec substitute_negations(Negations, List::[term()]) -> [term()] -%% -%% Negations = [{Key, Key}] -%% Key = term() -%% %% @doc Substitutes keys of boolean-valued properties and simultaneously %% negates their values. For each entry in <code>List</code>, if it is %% associated with some key <code>K1</code> such that <code>{K1, @@ -443,7 +431,10 @@ substitute_aliases_1([], P) -> %% @see substitute_aliases/2 %% @see normalize/2 --spec substitute_negations(negations(), List::[term()]) -> [term()]. +-spec substitute_negations(Negations, List) -> List when + Negations :: [{Key, Key}], + Key :: term(), + List :: [term()]. substitute_negations(As, Props) -> [substitute_negations_1(As, P) || P <- Props]. @@ -472,10 +463,6 @@ substitute_negations_1([], P) -> %% --------------------------------------------------------------------- -%% @spec expand(Expansions, List::[term()]) -> [term()] -%% -%% Expansions = [{property(), [term()]}] -%% %% @doc Expands particular properties to corresponding sets of %% properties (or other terms). For each pair <code>{Property, %% Expansion}</code> in <code>Expansions</code>, if <code>E</code> is @@ -510,7 +497,9 @@ substitute_negations_1([], P) -> %% %% @see normalize/2 --spec expand(Expansions::expansions(), [term()]) -> [term()]. +-spec expand(Expansions, List) -> List when + Expansions :: [{Property :: property(), Expansion :: [term()]}], + List :: [term()]. expand(Es, Ps) when is_list(Ps) -> Es1 = [{property(P), V} || {P, V} <- Es], @@ -589,15 +578,6 @@ flatten([]) -> %% --------------------------------------------------------------------- -%% @spec normalize(List::[term()], Stages::[Operation]) -> [term()] -%% -%% Operation = {aliases, Aliases} | {negations, Negations} -%% | {expand, Expansions} -%% Aliases = [{Key, Key}] -%% Negations = [{Key, Key}] -%% Key = term() -%% Expansions = [{property(), [term()]}] -%% %% @doc Passes <code>List</code> through a sequence of %% substitution/expansion stages. For an <code>aliases</code> operation, %% the function <code>substitute_aliases/2</code> is applied using the @@ -619,11 +599,15 @@ flatten([]) -> %% @see expand/2 %% @see compact/1 --type operation() :: {'aliases', aliases()} - | {'negations', negations()} - | {'expand', expansions()}. - --spec normalize(List::[term()], Stages::[operation()]) -> [term()]. +-spec normalize(List, Stages) -> List when + List :: [term()], + Stages :: [Operation], + Operation :: {'aliases', Aliases} + | {'negations', Negations} + | {'expand', Expansions}, + Aliases :: [{Key, Key}], + Negations :: [{Key, Key}], + Expansions :: [{Property :: property(), Expansion :: [term()]}]. normalize(L, [{aliases, As} | Xs]) -> normalize(substitute_aliases(As, L), Xs); @@ -636,10 +620,6 @@ normalize(L, []) -> %% --------------------------------------------------------------------- -%% @spec split(List::[term()], Keys::[term()]) -> {Lists, Rest} -%% Lists = [[term()]] -%% Rest = [term()] -%% %% @doc Partitions <code>List</code> into a list of sublists and a %% remainder. <code>Lists</code> contains one sublist for each key in %% <code>Keys</code>, in the corresponding order. The relative order of @@ -654,7 +634,11 @@ normalize(L, []) -> %% {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}</pre> %% </p> --spec split(List::[term()], Keys::[term()]) -> {[[term()]], [term()]}. +-spec split(List, Keys) -> {Lists, Rest} when + List :: [term()], + Keys :: [term()], + Lists :: [[term()]], + Rest :: [term()]. split(List, Keys) -> {Store, Rest} = split(List, dict:from_list([{K, []} || K <- Keys]), []), diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl index bc6944e520..f5e180b4bd 100644 --- a/lib/stdlib/src/qlc.erl +++ b/lib/stdlib/src/qlc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -60,7 +60,7 @@ -record(qlc_table, % qlc:table/2 {trav_fun, % traverse fun - trav_MS, % bool(); true iff traverse fun takes a match spec + trav_MS, % boolean(); true iff traverse fun takes a match spec pre_fun, post_fun, info_fun, @@ -110,12 +110,12 @@ -record(qlc_cursor, {c}). -record(qlc_opt, - {unique = false, % bool() - cache = false, % bool() | list (true~ets, false~no) + {unique = false, % boolean() + cache = false, % boolean() | list (true~ets, false~no) max_lookup = -1, % int() >= 0 | -1 (represents infinity) join = any, % any | nested_loop | merge | lookup tmpdir = "", % global tmpdir - lookup = any, % any | bool() + lookup = any, % any | boolean() max_list = ?MAX_LIST_SIZE, % int() >= 0 tmpdir_usage = allowed % allowed | not_allowed % | warning_msg | error_msg | info_msg @@ -123,7 +123,9 @@ -record(setup, {parent}). --define(THROWN_ERROR, {?MODULE, throw_error, _}). +-define(THROWN_ERROR, {?MODULE, throw_error, _, _}). + +-export_type([query_handle/0]). %%% A query handle is a tuple {qlc_handle, Handle} where Handle is one %%% of #qlc_append, #qlc_table, #qlc_sort, and #qlc_lc. @@ -144,6 +146,35 @@ get_handle(_) -> %%% Exported functions %%% +-type(query_list_comprehension() :: term()). +-opaque(query_cursor() :: {qlc_cursor, term()}). +-opaque(query_handle() :: {qlc_handle, term()}). +-type(query_handle_or_list() :: query_handle() | list()). +-type(answers() :: [answer()]). +-type(answer() :: term()). +-type(abstract_expr() :: erl_parse:abstract_expr()). +-type(match_expression() :: ets:match_spec()). +-type(spawn_options() :: default | [proc_lib:spawn_option()]). +-type(sort_options() :: [sort_option()] | sort_option()). +-type(sort_option() :: {compressed, boolean()} + | {no_files, no_files()} + | {order, order()} + | {size, pos_integer()} + | {tmpdir, tmp_directory()} + | {unique, boolean()}). +-type(order() :: ascending | descending | order_fun()). +-type(order_fun() :: fun((term(), term()) -> boolean())). +-type(tmp_directory() :: [] | file:name()). +-type(no_files() :: pos_integer()). % > 1 +-type(key_pos() :: pos_integer() | [pos_integer()]). +-type(max_list_size() :: non_neg_integer()). +-type(cache() :: ets | list | no). +-type(tmp_file_usage() :: allowed | not_allowed | info_msg + | warning_msg | error_msg). + +-spec(append(QHL) -> QH when + QHL :: [query_handle_or_list()], + QH :: query_handle()). append(QHs) -> Hs = [case get_handle(QH) of badarg -> erlang:error(badarg, [QHs]); @@ -151,6 +182,10 @@ append(QHs) -> end || QH <- QHs], #qlc_handle{h = #qlc_append{hl = Hs}}. +-spec(append(QH1, QH2) -> QH3 when + QH1 :: query_handle_or_list(), + QH2 :: query_handle_or_list(), + QH3 :: query_handle()). append(QH1, QH2) -> Hs = [case get_handle(QH) of badarg -> erlang:error(badarg, [QH1, QH2]); @@ -158,9 +193,22 @@ append(QH1, QH2) -> end || QH <- [QH1, QH2]], #qlc_handle{h = #qlc_append{hl = Hs}}. +-spec(cursor(QH) -> Cursor when + QH :: query_handle_or_list(), + Cursor :: query_cursor()). cursor(QH) -> cursor(QH, []). +-spec(cursor(QH, Options) -> Cursor when + QH :: query_handle_or_list(), + Options :: [Option] | Option, + Option :: {cache_all, cache()} | cache_all + | {max_list_size, max_list_size()} + | {spawn_options, spawn_options()} + | {tmpdir_usage, tmp_file_usage()} + | {tmpdir, tmp_directory()} + | {unique_all, boolean()} | unique_all, + Cursor :: query_cursor()). cursor(QH, Options) -> case {options(Options, [unique_all, cache_all, tmpdir, spawn_options, max_list_size, @@ -179,6 +227,8 @@ cursor(QH, Options) -> end end. +-spec(delete_cursor(QueryCursor) -> ok when + QueryCursor :: query_cursor()). delete_cursor(#qlc_cursor{c = {_, Owner}}=C) when Owner =/= self() -> erlang:error(not_cursor_owner, [C]); delete_cursor(#qlc_cursor{c = {Pid, _}}) -> @@ -186,15 +236,47 @@ delete_cursor(#qlc_cursor{c = {Pid, _}}) -> delete_cursor(T) -> erlang:error(badarg, [T]). +-spec(e(QH) -> Answers | Error when + QH :: query_handle_or_list(), + Answers :: answers(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). e(QH) -> eval(QH, []). +-spec(e(QH, Options) -> Answers | Error when + QH :: query_handle_or_list(), + Options :: [Option] | Option, + Option :: {cache_all, cache()} | cache_all + | {max_list_size, max_list_size()} + | {tmpdir_usage, tmp_file_usage()} + | {tmpdir, tmp_directory()} + | {unique_all, boolean()} | unique_all, + Answers :: answers(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). e(QH, Options) -> eval(QH, Options). +-spec(eval(QH) -> Answers | Error when + QH :: query_handle_or_list(), + Answers :: answers(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). eval(QH) -> eval(QH, []). +-spec(eval(QH, Options) -> Answers | Error when + QH :: query_handle_or_list(), + Answers :: answers(), + Options :: [Option] | Option, + Option :: {cache_all, cache()} | cache_all + | {max_list_size, max_list_size()} + | {tmpdir_usage, tmp_file_usage()} + | {tmpdir, tmp_directory()} + | {unique_all, boolean()} | unique_all, + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). eval(QH, Options) -> case {options(Options, [unique_all, cache_all, tmpdir, max_list_size, tmpdir_usage]), @@ -226,9 +308,35 @@ eval(QH, Options) -> end end. +-spec(fold(Function, Acc0, QH) -> + Acc1 | Error when + QH :: query_handle_or_list(), + Function :: fun((answer(), AccIn) -> AccOut), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). fold(Fun, Acc0, QH) -> fold(Fun, Acc0, QH, []). +-spec(fold(Function, Acc0, QH, Options) -> + Acc1 | Error when + QH :: query_handle_or_list(), + Function :: fun((answer(), AccIn) -> AccOut), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + Options :: [Option] | Option, + Option :: {cache_all, cache()} | cache_all + | {max_list_size, max_list_size()} + | {tmpdir_usage, tmp_file_usage()} + | {tmpdir, tmp_directory()} + | {unique_all, boolean()} | unique_all, + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). fold(Fun, Acc0, QH, Options) -> case {options(Options, [unique_all, cache_all, tmpdir, max_list_size, tmpdir_usage]), @@ -258,6 +366,9 @@ fold(Fun, Acc0, QH, Options) -> end end. +-spec(format_error(Error) -> Chars when + Error :: {error, module(), term()}, + Chars :: io_lib:chars()). format_error(not_a_query_list_comprehension) -> io_lib:format("argument is not a query list comprehension", []); format_error({used_generator_variable, V}) -> @@ -295,9 +406,29 @@ format_error({error, Module, Reason}) -> format_error(E) -> io_lib:format("~p~n", [E]). +-spec(info(QH) -> Info when + QH :: query_handle_or_list(), + Info :: abstract_expr() | string()). info(QH) -> info(QH, []). +-spec(info(QH, Options) -> Info when + QH :: query_handle_or_list(), + Options :: [Option] | Option, + Option :: EvalOption | ReturnOption, + EvalOption :: {cache_all, cache()} | cache_all + | {max_list_size, max_list_size()} + | {tmpdir_usage, tmp_file_usage()} + | {tmpdir, tmp_directory()} + | {unique_all, boolean()} | unique_all, + ReturnOption :: {depth, Depth} + | {flat, boolean()} + | {format, Format} + | {n_elements, NElements}, + Depth :: infinity | non_neg_integer(), + Format :: abstract_code | string, + NElements :: infinity | pos_integer(), + Info :: abstract_expr() | string()). info(QH, Options) -> case {options(Options, [unique_all, cache_all, flat, format, n_elements, depth, tmpdir, max_list_size, tmpdir_usage]), @@ -333,9 +464,18 @@ info(QH, Options) -> end end. +-spec(keysort(KeyPos, QH1) -> QH2 when + KeyPos :: key_pos(), + QH1 :: query_handle_or_list(), + QH2 :: query_handle()). keysort(KeyPos, QH) -> keysort(KeyPos, QH, []). +-spec(keysort(KeyPos, QH1, SortOptions) -> QH2 when + KeyPos :: key_pos(), + SortOptions :: sort_options(), + QH1 :: query_handle_or_list(), + QH2 :: query_handle()). keysort(KeyPos, QH, Options) -> case {is_keypos(KeyPos), options(Options, [tmpdir, order, unique, compressed, @@ -354,9 +494,22 @@ keysort(KeyPos, QH, Options) -> -define(DEFAULT_NUM_OF_ANSWERS, 10). +-spec(next_answers(QueryCursor) -> + Answers | Error when + QueryCursor :: query_cursor(), + Answers :: answers(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). next_answers(C) -> next_answers(C, ?DEFAULT_NUM_OF_ANSWERS). +-spec(next_answers(QueryCursor, NumberOfAnswers) -> + Answers | Error when + QueryCursor :: query_cursor(), + Answers :: answers(), + NumberOfAnswers :: all_remaining | pos_integer(), + Error :: {error, module(), Reason}, + Reason :: file_sorter:reason()). next_answers(#qlc_cursor{c = {_, Owner}}=C, NumOfAnswers) when Owner =/= self() -> erlang:error(not_cursor_owner, [C, NumOfAnswers]); @@ -370,14 +523,35 @@ next_answers(#qlc_cursor{c = {Pid, _}}=C, NumOfAnswers) -> next_answers(T1, T2) -> erlang:error(badarg, [T1, T2]). +-spec(parse_transform(Forms, Options) -> Forms2 when + Forms :: [erl_parse:abstract_form()], + Forms2 :: [erl_parse:abstract_form()], + Options :: [Option], + Option :: type_checker | compile:option()). + parse_transform(Forms, Options) -> qlc_pt:parse_transform(Forms, Options). %% The funcspecs qlc:q/1 and qlc:q/2 are known by erl_eval.erl and %% erl_lint.erl. +-spec(q(QLC) -> QH when + QLC :: query_list_comprehension(), + QH :: query_handle()). q(QLC_lc) -> q(QLC_lc, []). +-spec(q(QLC, Options) -> QH when + QH :: query_handle(), + Options :: [Option] | Option, + Option :: {max_lookup, MaxLookup} + | {cache, cache()} | cache + | {join, Join} + | {lookup, Lookup} + | {unique, boolean()} | unique, + MaxLookup :: non_neg_integer() | infinity, + Join :: any | lookup | merge | nested_loop, + Lookup :: boolean() | any, + QLC :: query_list_comprehension()). q(#qlc_lc{}=QLC_lc, Options) -> case options(Options, [unique, cache, max_lookup, join, lookup]) of [Unique, Cache, Max, Join, Lookup] -> @@ -390,9 +564,16 @@ q(#qlc_lc{}=QLC_lc, Options) -> q(T1, T2) -> erlang:error(badarg, [T1, T2]). +-spec(sort(QH1) -> QH2 when + QH1 :: query_handle_or_list(), + QH2 :: query_handle()). sort(QH) -> sort(QH, []). +-spec(sort(QH1, SortOptions) -> QH2 when + SortOptions :: sort_options(), + QH1 :: query_handle_or_list(), + QH2 :: query_handle()). sort(QH, Options) -> case {options(Options, [tmpdir, order, unique, compressed, size, no_files]), get_handle(QH)} of @@ -406,14 +587,47 @@ sort(QH, Options) -> end. %% Note that the generated code is evaluated by (the slow) erl_eval. +-spec(string_to_handle(QueryString) -> QH | Error when + QueryString :: string(), + QH :: query_handle(), + Error :: {error, module(), Reason}, + Reason :: erl_parse:error_info() | erl_scan:error_info()). string_to_handle(Str) -> string_to_handle(Str, []). +-spec(string_to_handle(QueryString, Options) -> QH | Error when + QueryString :: string(), + Options :: [Option] | Option, + Option :: {max_lookup, MaxLookup} + | {cache, cache()} | cache + | {join, Join} + | {lookup, Lookup} + | {unique, boolean()} | unique, + MaxLookup :: non_neg_integer() | infinity, + Join :: any | lookup | merge | nested_loop, + Lookup :: boolean() | any, + QH :: query_handle(), + Error :: {error, module(), Reason}, + Reason :: erl_parse:error_info() | erl_scan:error_info()). string_to_handle(Str, Options) -> - string_to_handle(Str, Options, []). - -string_to_handle(Str, Options, Bindings) when is_list(Str), - is_list(Bindings) -> + string_to_handle(Str, Options, erl_eval:new_bindings()). + +-spec(string_to_handle(QueryString, Options, Bindings) -> QH | Error when + QueryString :: string(), + Options :: [Option] | Option, + Option :: {max_lookup, MaxLookup} + | {cache, cache()} | cache + | {join, Join} + | {lookup, Lookup} + | {unique, boolean()} | unique, + MaxLookup :: non_neg_integer() | infinity, + Join :: any | lookup | merge | nested_loop, + Lookup :: boolean() | any, + Bindings :: erl_eval:binding_struct(), + QH :: query_handle(), + Error :: {error, module(), Reason}, + Reason :: erl_parse:error_info() | erl_scan:error_info()). +string_to_handle(Str, Options, Bindings) when is_list(Str) -> case options(Options, [unique, cache, max_lookup, join, lookup]) of badarg -> erlang:error(badarg, [Str, Options, Bindings]); @@ -447,6 +661,51 @@ string_to_handle(Str, Options, Bindings) when is_list(Str), string_to_handle(T1, T2, T3) -> erlang:error(badarg, [T1, T2, T3]). +-spec(table(TraverseFun, Options) -> QH when + TraverseFun :: TraverseFun0 | TraverseFun1, + TraverseFun0 :: fun(() -> TraverseResult), + TraverseFun1 :: fun((match_expression()) -> TraverseResult), + TraverseResult :: Objects | term(), + Objects :: [] | [term() | ObjectList], + ObjectList :: TraverseFun0 | Objects, + Options :: [Option] | Option, + Option :: {format_fun, FormatFun} + | {info_fun, InfoFun} + | {lookup_fun, LookupFun} + | {parent_fun, ParentFun} + | {post_fun, PostFun} + | {pre_fun, PreFun} + | {key_equality, KeyComparison}, + FormatFun :: undefined | fun((SelectedObjects) -> FormatedTable), + SelectedObjects :: all + | {all, NElements, DepthFun} + | {match_spec, match_expression()} + | {lookup, Position, Keys} + | {lookup, Position, Keys, NElements, DepthFun}, + NElements :: infinity | pos_integer(), + DepthFun :: fun((term()) -> term()), + FormatedTable :: {Mod, Fun, Args} + | abstract_expr() + | string(), + InfoFun :: undefined | fun((InfoTag) -> InfoValue), + InfoTag :: indices | is_unique_objects | keypos | num_of_objects, + InfoValue :: undefined | term(), + LookupFun :: undefined | fun((Position, Keys) -> LookupResult), + LookupResult :: [term()] | term(), + ParentFun :: undefined | fun(() -> ParentFunValue), + PostFun :: undefined | fun(() -> term()), + PreFun :: undefined | fun((PreArgs) -> term()), + PreArgs :: [PreArg], + PreArg :: {parent_value, ParentFunValue} | {stop_fun, StopFun}, + ParentFunValue :: undefined | term(), + StopFun :: undefined | fun(() -> term()), + KeyComparison :: '=:=' | '==', + Position :: pos_integer(), + Keys :: [term()], + Mod :: atom(), + Fun :: atom(), + Args :: [term()], + QH :: query_handle()). table(TraverseFun, Options) when is_function(TraverseFun) -> case {is_function(TraverseFun, 0), IsFun1 = is_function(TraverseFun, 1)} of @@ -472,6 +731,11 @@ table(TraverseFun, Options) when is_function(TraverseFun) -> table(T1, T2) -> erlang:error(badarg, [T1, T2]). +-spec(transform_from_evaluator(LC, Bs) -> Expr when + LC :: abstract_expr(), + Expr :: abstract_expr(), + Bs :: erl_eval:binding_struct()). + transform_from_evaluator(LC, Bs0) -> qlc_pt:transform_from_evaluator(LC, Bs0). @@ -722,8 +986,8 @@ listify(T) -> %% Optimizations to be carried out. -record(optz, - {unique = false, % bool() - cache = false, % bool() | list + {unique = false, % boolean() + cache = false, % boolean() | list join_option = any, % constraint set by the 'join' option fast_join = no, % no | #qlc_join. 'no' means nested loop. opt % #qlc_opt @@ -756,8 +1020,8 @@ listify(T) -> lu_skip_quals = [], % qualifiers to skip due to lookup join = {[],[]}, % {Lookup, Merge} n_objs = undefined, % for join (not used yet) - is_unique_objects = false, % bool() - is_cached = false % bool() (true means 'ets' or 'list') + is_unique_objects = false, % boolean() + is_cached = false % boolean() (true means 'ets' or 'list') }). %%% Cursor process functions. @@ -1143,20 +1407,20 @@ monitor_request(Pid, Req) -> %% QueryDesc = {qlc, TemplateDesc, [QualDesc], [QueryOpt]} %% | {table, TableDesc} %% | {append, [QueryDesc]} -%% | {sort, QueryDesc, [SortOption]} -%% | {keysort, KeyPos, QueryDesc, [SortOption]} +%% | {sort, QueryDesc, [sort_option()]} +%% | {keysort, key_pos(), QueryDesc, [sort_option()]} %% | {list, list()} -%% | {list, QueryDesc, MatchExpression} +%% | {list, QueryDesc, match_expression()} %% TableDesc = {Mod, Fun, Args} -%% | AbstractExpression -%% | character_list() +%% | erl_parse:abstract_expr() +%% | string() %% Mod = module() %% Fun = atom() %% Args = [term()] %% QualDesc = FilterDesc %% | {generate, PatternDesc, QueryDesc} -%% QueryOpt = {cache, bool()} | cache -%% | {unique, bool()} | unique +%% QueryOpt = {cache, boolean()} | cache +%% | {unique, boolean()} | unique %% FilterDesc = PatternDesc = TemplateDesc = binary() le_info(#prepared{qh = #simple_qlc{le = LE, p = P, line = L, optz = Optz}}, @@ -3437,7 +3701,8 @@ lookup_join(F1, C1, LuF, C2, Rev) -> maybe_error_logger(allowed, _) -> ok; maybe_error_logger(Name, Why) -> - [_, _, {?MODULE,maybe_error_logger,_} | Stacktrace] = expand_stacktrace(), + [_, _, {?MODULE,maybe_error_logger,_,_} | Stacktrace] = + expand_stacktrace(), Trimmer = fun(M, _F, _A) -> M =:= erl_eval end, Formater = fun(Term, I) -> io_lib:print(Term, I, 80, -1) end, X = lib:format_stacktrace(1, Stacktrace, Trimmer, Formater), @@ -3456,7 +3721,7 @@ expand_stacktrace() -> expand_stacktrace(D) -> _ = erlang:system_flag(backtrace_depth, D), {'EXIT', {foo, Stacktrace}} = (catch erlang:error(foo)), - L = lists:takewhile(fun({M,_,_}) -> M =/= ?MODULE + L = lists:takewhile(fun({M,_,_,_}) -> M =/= ?MODULE end, lists:reverse(Stacktrace)), if length(L) < 3 andalso length(Stacktrace) =:= D -> diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl index 24378a0698..21504d707b 100644 --- a/lib/stdlib/src/qlc_pt.erl +++ b/lib/stdlib/src/qlc_pt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -63,6 +63,12 @@ %%% Exported functions %%% +-spec(parse_transform(Forms, Options) -> Forms2 when + Forms :: [erl_parse:abstract_form()], + Forms2 :: [erl_parse:abstract_form()], + Options :: [Option], + Option :: type_checker | compile:option()). + parse_transform(Forms, Options) -> ?DEBUG("qlc Parse Transform~n", []), State = #state{imp = is_qlc_q_imported(Forms), @@ -96,10 +102,20 @@ parse_transform(Forms, Options) -> end end. +-spec(transform_from_evaluator(LC, Bs) -> Expr when + LC :: erl_parse:abstract_expr(), + Expr :: erl_parse:abstract_expr(), + Bs :: erl_eval:binding_struct()). + transform_from_evaluator(LC, Bindings) -> ?DEBUG("qlc Parse Transform (Evaluator Version)~n", []), transform_expression(LC, Bindings, false). +-spec(transform_expression(LC, Bs) -> Expr when + LC :: erl_parse:abstract_expr(), + Expr :: erl_parse:abstract_expr(), + Bs :: erl_eval:binding_struct()). + transform_expression(LC, Bindings) -> transform_expression(LC, Bindings, true). diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl index c09079e8d2..afe917b151 100644 --- a/lib/stdlib/src/queue.erl +++ b/lib/stdlib/src/queue.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -56,14 +56,14 @@ new() -> {[],[]}. %{RearList,FrontList} %% O(1) --spec is_queue(term()) -> boolean(). +-spec is_queue(Term :: term()) -> boolean(). is_queue({R,F}) when is_list(R), is_list(F) -> true; is_queue(_) -> false. %% O(1) --spec is_empty(queue()) -> boolean(). +-spec is_empty(Q :: queue()) -> boolean(). is_empty({[],[]}) -> true; is_empty({In,Out}) when is_list(In), is_list(Out) -> @@ -72,14 +72,14 @@ is_empty(Q) -> erlang:error(badarg, [Q]). %% O(len(Q)) --spec len(queue()) -> non_neg_integer(). +-spec len(Q :: queue()) -> non_neg_integer(). len({R,F}) when is_list(R), is_list(F) -> length(R)+length(F); len(Q) -> erlang:error(badarg, [Q]). %% O(len(Q)) --spec to_list(queue()) -> list(). +-spec to_list(Q :: queue()) -> list(). to_list({In,Out}) when is_list(In), is_list(Out) -> Out++lists:reverse(In, []); to_list(Q) -> @@ -88,7 +88,7 @@ to_list(Q) -> %% Create queue from list %% %% O(length(L)) --spec from_list(list()) -> queue(). +-spec from_list(L :: list()) -> queue(). from_list(L) when is_list(L) -> f2r(L); from_list(L) -> @@ -97,7 +97,7 @@ from_list(L) -> %% Return true or false depending on if element is in queue %% %% O(length(Q)) worst case --spec member(term(), queue()) -> boolean(). +-spec member(Item :: term(), Q :: queue()) -> boolean(). member(X, {R,F}) when is_list(R), is_list(F) -> lists:member(X, R) orelse lists:member(X, F); member(X, Q) -> @@ -110,7 +110,7 @@ member(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in(term(), queue()) -> queue(). +-spec in(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). in(X, {[_]=In,[]}) -> {[X], In}; in(X, {In,Out}) when is_list(In), is_list(Out) -> @@ -122,7 +122,7 @@ in(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in_r(term(), queue()) -> queue(). +-spec in_r(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). in_r(X, {[],[_]=F}) -> {F,[X]}; in_r(X, {R,F}) when is_list(R), is_list(F) -> @@ -133,7 +133,9 @@ in_r(X, Q) -> %% Take from head/front %% %% O(1) amortized, O(len(Q)) worst case --spec out(queue()) -> {'empty' | {'value',term()}, queue()}. +-spec out(Q1 :: queue()) -> + {{value, Item :: term()}, Q2 :: queue()} | + {empty, Q1 :: queue()}. out({[],[]}=Q) -> {empty,Q}; out({[V],[]}) -> @@ -151,7 +153,9 @@ out(Q) -> %% Take from tail/rear %% %% O(1) amortized, O(len(Q)) worst case --spec out_r(queue()) -> {'empty' | {'value',term()}, queue()}. +-spec out_r(Q1 :: queue()) -> + {{value, Item :: term()}, Q2 :: queue()} | + {empty, Q1 :: queue()}. out_r({[],[]}=Q) -> {empty,Q}; out_r({[],[V]}) -> @@ -172,7 +176,7 @@ out_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get(queue()) -> term(). +-spec get(Q :: queue()) -> Item :: term(). get({[],[]}=Q) -> erlang:error(empty, [Q]); get({R,F}) when is_list(R), is_list(F) -> @@ -191,7 +195,7 @@ get([_|R], []) -> % malformed queue -> O(len(Q)) %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get_r(queue()) -> term(). +-spec get_r(Q :: queue()) -> Item :: term(). get_r({[],[]}=Q) -> erlang:error(empty, [Q]); get_r({[H|_],F}) when is_list(F) -> @@ -206,7 +210,7 @@ get_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek(queue()) -> 'empty' | {'value',term()}. +-spec peek(Q :: queue()) -> empty | {value,Item :: term()}. peek({[],[]}) -> empty; peek({R,[H|_]}) when is_list(R) -> @@ -221,7 +225,7 @@ peek(Q) -> %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek_r(queue()) -> 'empty' | {'value',term()}. +-spec peek_r(Q :: queue()) -> empty | {value,Item :: term()}. peek_r({[],[]}) -> empty; peek_r({[H|_],F}) when is_list(F) -> @@ -236,7 +240,7 @@ peek_r(Q) -> %% Remove the first element and return resulting queue %% %% O(1) amortized --spec drop(queue()) -> queue(). +-spec drop(Q1 :: queue()) -> Q2 :: queue(). drop({[],[]}=Q) -> erlang:error(empty, [Q]); drop({[_],[]}) -> @@ -254,7 +258,7 @@ drop(Q) -> %% Remove the last element and return resulting queue %% %% O(1) amortized --spec drop_r(queue()) -> queue(). +-spec drop_r(Q1 :: queue()) -> Q2 :: queue(). drop_r({[],[]}=Q) -> erlang:error(empty, [Q]); drop_r({[],[_]}) -> @@ -275,7 +279,7 @@ drop_r(Q) -> %% Return reversed queue %% %% O(1) --spec reverse(queue()) -> queue(). +-spec reverse(Q1 :: queue()) -> Q2 :: queue(). reverse({R,F}) when is_list(R), is_list(F) -> {F,R}; reverse(Q) -> @@ -285,7 +289,7 @@ reverse(Q) -> %% %% Q2 empty: O(1) %% else: O(len(Q1)) --spec join(queue(), queue()) -> queue(). +-spec join(Q1 :: queue(), Q2 :: queue()) -> Q3 :: queue(). join({R,F}=Q, {[],[]}) when is_list(R), is_list(F) -> Q; join({[],[]}, {R,F}=Q) when is_list(R), is_list(F) -> @@ -299,7 +303,8 @@ join(Q1, Q2) -> %% %% N = 0..len(Q) %% O(max(N, len(Q))) --spec split(non_neg_integer(), queue()) -> {queue(),queue()}. +-spec split(N :: non_neg_integer(), Q1 :: queue()) -> + {Q2 :: queue(),Q3 :: queue()}. split(0, {R,F}=Q) when is_list(R), is_list(F) -> {{[],[]},Q}; split(N, {R,F}=Q) when is_integer(N), N >= 1, is_list(R), is_list(F) -> @@ -340,7 +345,8 @@ split_r1_to_f2(N, [X|R1], F1, R2, F2) -> %% %% Fun(_) -> List: O(length(List) * len(Q)) %% else: O(len(Q) --spec filter(fun((term()) -> boolean() | list()), queue()) -> queue(). +-spec filter(Fun, Q1 :: queue()) -> Q2 :: queue() when + Fun :: fun((Item :: term()) -> boolean() | list()). filter(Fun, {R0,F0}) when is_function(Fun, 1), is_list(R0), is_list(F0) -> F = filter_f(Fun, F0), R = filter_r(Fun, R0), @@ -416,7 +422,7 @@ filter_r(Fun, [X|R0]) -> %% Cons to head %% --spec cons(term(), queue()) -> queue(). +-spec cons(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). cons(X, Q) -> in_r(X, Q). @@ -425,7 +431,7 @@ cons(X, Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec head(queue()) -> term(). +-spec head(Q :: queue()) -> Item :: term(). head({[],[]}=Q) -> erlang:error(empty, [Q]); head({R,F}) when is_list(R), is_list(F) -> @@ -435,7 +441,7 @@ head(Q) -> %% Remove head element and return resulting queue %% --spec tail(queue()) -> queue(). +-spec tail(Q1 :: queue()) -> Q2 :: queue(). tail(Q) -> drop(Q). @@ -443,22 +449,22 @@ tail(Q) -> %% Cons to tail %% --spec snoc(queue(), term()) -> queue(). +-spec snoc(Q1 :: queue(), Item :: term()) -> Q2 :: queue(). snoc(Q, X) -> in(X, Q). %% Return last element --spec daeh(queue()) -> term(). +-spec daeh(Q :: queue()) -> Item :: term(). daeh(Q) -> get_r(Q). --spec last(queue()) -> term(). +-spec last(Q :: queue()) -> Item :: term(). last(Q) -> get_r(Q). %% Remove last element and return resulting queue --spec liat(queue()) -> queue(). +-spec liat(Q1 :: queue()) -> Q2 :: queue(). liat(Q) -> drop_r(Q). --spec lait(queue()) -> queue(). +-spec lait(Q1 :: queue()) -> Q2 :: queue(). lait(Q) -> drop_r(Q). %% Oops, mis-spelled 'tail' reversed. Forget this one. --spec init(queue()) -> queue(). +-spec init(Q1 :: queue()) -> Q2 :: queue(). init(Q) -> drop_r(Q). %%-------------------------------------------------------------------------- diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl index 606edbb1fb..d7b51a151c 100644 --- a/lib/stdlib/src/random.erl +++ b/lib/stdlib/src/random.erl @@ -57,7 +57,10 @@ seed() -> %% seed({A1, A2, A3}) %% Seed random number generation --spec seed({integer(), integer(), integer()}) -> 'undefined' | ran(). +-spec seed({A1, A2, A3}) -> 'undefined' | ran() when + A1 :: integer(), + A2 :: integer(), + A3 :: integer(). seed({A1, A2, A3}) -> seed(A1, A2, A3). @@ -65,7 +68,10 @@ seed({A1, A2, A3}) -> %% seed(A1, A2, A3) %% Seed random number generation --spec seed(integer(), integer(), integer()) -> 'undefined' | ran(). +-spec seed(A1, A2, A3) -> 'undefined' | ran() when + A1 :: integer(), + A2 :: integer(), + A3 :: integer(). seed(A1, A2, A3) -> seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are @@ -99,7 +105,8 @@ uniform() -> %% Given an integer N >= 1, uniform(N) returns a random integer %% between 1 and N. --spec uniform(pos_integer()) -> pos_integer(). +-spec uniform(N) -> pos_integer() when + N :: pos_integer(). uniform(N) when is_integer(N), N >= 1 -> trunc(uniform() * N) + 1. @@ -110,7 +117,9 @@ uniform(N) when is_integer(N), N >= 1 -> %% uniform_s(State) -> {F, NewState} %% Returns a random float between 0 and 1. --spec uniform_s(ran()) -> {float(), ran()}. +-spec uniform_s(State0) -> {float(), State1} when + State0 :: ran(), + State1 :: ran(). uniform_s({A1, A2, A3}) -> B1 = (A1*171) rem ?PRIME1, @@ -123,7 +132,10 @@ uniform_s({A1, A2, A3}) -> %% Given an integer N >= 1, uniform(N) returns a random integer %% between 1 and N. --spec uniform_s(pos_integer(), ran()) -> {integer(), ran()}. +-spec uniform_s(N, State0) -> {integer(), State1} when + N :: pos_integer(), + State0 :: ran(), + State1 :: ran(). uniform_s(N, State0) when is_integer(N), N >= 1 -> {F, State1} = uniform_s(State0), diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl index e2cc9f57ce..99bcbd722e 100644 --- a/lib/stdlib/src/re.erl +++ b/lib/stdlib/src/re.erl @@ -19,15 +19,46 @@ -module(re). -export([grun/3,urun/3,ucompile/2,replace/3,replace/4,split/2,split/3]). +%-opaque mp() :: {re_pattern, _, _, _}. +-type mp() :: {re_pattern, _, _, _}. + +-type nl_spec() :: cr | crlf | lf | anycrlf | any. + +-type compile_option() :: unicode | anchored | caseless | dollar_endonly + | dotall | extended | firstline | multiline + | no_auto_capture | dupnames | ungreedy + | {newline, nl_spec()}| bsr_anycrlf + | bsr_unicode. + %% Emulator builtins in this module: %% re:compile/1 %% re:compile/2 %% re:run/2 %% re:run/3 +-spec split(Subject, RE) -> SplitList when + Subject :: iodata() | unicode:charlist(), + RE :: mp() | iodata(), + SplitList :: [iodata() | unicode:charlist()]. + split(Subject,RE) -> split(Subject,RE,[]). +-spec split(Subject, RE, Options) -> SplitList when + Subject :: iodata() | unicode:charlist(), + RE :: mp() | iodata() | unicode:charlist(), + Options :: [ Option ], + Option :: anchored | global | notbol | noteol | notempty + | {offset, non_neg_integer()} | {newline, nl_spec()} + | bsr_anycrlf | bsr_unicode | {return, ReturnType} + | {parts, NumParts} | group | trim | CompileOpt, + NumParts :: non_neg_integer() | infinity, + ReturnType :: iodata | list | binary, + CompileOpt :: compile_option(), + SplitList :: [RetData] | [GroupedRetData], + GroupedRetData :: [RetData], + RetData :: iodata() | unicode:charlist() | binary() | list(). + split(Subject,RE,Options) -> try {NewOpt,Convert,Unicode,Limit,Strip,Group} = @@ -197,10 +228,26 @@ compile_split(Pat,Options0) when not is_tuple(Pat) -> compile_split(_,_) -> throw(badre). +-spec replace(Subject, RE, Replacement) -> iodata() | unicode:charlist() when + Subject :: iodata() | unicode:charlist(), + RE :: mp() | iodata(), + Replacement :: iodata() | unicode:charlist(). replace(Subject,RE,Replacement) -> replace(Subject,RE,Replacement,[]). +-spec replace(Subject, RE, Replacement, Options) -> iodata() | unicode:charlist() when + Subject :: iodata() | unicode:charlist(), + RE :: mp() | iodata() | unicode:charlist(), + Replacement :: iodata() | unicode:charlist(), + Options :: [Option], + Option :: anchored | global | notbol | noteol | notempty + | {offset, non_neg_integer()} | {newline, NLSpec} | bsr_anycrlf + | bsr_unicode | {return, ReturnType} | CompileOpt, + ReturnType :: iodata | list | binary, + CompileOpt :: compile_option(), + NLSpec :: cr | crlf | lf | anycrlf | any. + replace(Subject,RE,Replacement,Options) -> try {NewOpt,Convert,Unicode} = @@ -526,10 +573,10 @@ ucompile(RE,Options) -> re:compile(unicode:characters_to_binary(RE,unicode),Options) catch error:AnyError -> - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} = (catch erlang:error(new_stacktrace, [RE,Options])), - erlang:raise(error,AnyError,[{Mod,compile,L}|Rest]) + erlang:raise(error,AnyError,[{Mod,compile,L,Loc}|Rest]) end. @@ -538,10 +585,10 @@ urun(Subject,RE,Options) -> urun2(Subject,RE,Options) catch error:AnyError -> - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} = (catch erlang:error(new_stacktrace, [Subject,RE,Options])), - erlang:raise(error,AnyError,[{Mod,run,L}|Rest]) + erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest]) end. urun2(Subject0,RE0,Options0) -> @@ -578,20 +625,20 @@ grun(Subject,RE,{Options,NeedClean}) -> grun2(Subject,RE,{Options,NeedClean}) catch error:AnyError -> - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} = (catch erlang:error(new_stacktrace, [Subject,RE,Options])), - erlang:raise(error,AnyError,[{Mod,run,L}|Rest]) + erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest]) end; grun(Subject,RE,{Options,NeedClean,OrigRE}) -> try grun2(Subject,RE,{Options,NeedClean}) catch error:AnyError -> - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} = (catch erlang:error(new_stacktrace, [Subject,OrigRE,Options])), - erlang:raise(error,AnyError,[{Mod,run,L}|Rest]) + erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest]) end. grun2(Subject,RE,{Options,NeedClean}) -> diff --git a/lib/stdlib/src/regexp.erl b/lib/stdlib/src/regexp.erl index 8f5994bbee..65f9ca247d 100644 --- a/lib/stdlib/src/regexp.erl +++ b/lib/stdlib/src/regexp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,6 +37,9 @@ -import(string, [substr/2,substr/3]). -import(lists, [reverse/1]). +-type errordesc() :: term(). +-opaque regexp() :: term(). + %% -type matchres() = {match,Start,Length} | nomatch | {error,E}. %% -type subres() = {ok,RepString,RepCount} | {error,E}. %% -type splitres() = {ok,[SubString]} | {error,E}. @@ -287,6 +290,10 @@ re_apply_or(R1, nomatch) -> R1. %% Convert a sh style regexp into a full AWK one. The main difficulty is %% getting character sets right as the conventions are different. +-spec sh_to_awk(ShRegExp) -> AwkRegExp when + ShRegExp :: string(), + AwkRegExp :: string(). + sh_to_awk(Sh) -> "^(" ++ sh_to_awk_1(Sh). %Fix the beginning sh_to_awk_1([$*|Sh]) -> %This matches any string @@ -336,6 +343,12 @@ special_char(_C) -> false. %% parse(RegExp) -> {ok,RE} | {error,E}. %% Parse the regexp described in the string RegExp. +-spec parse(RegExp) -> ParseRes when + RegExp :: string(), + ParseRes :: {ok, RE} | {error, Error}, + RE :: regexp(), + Error :: errordesc(). + parse(S) -> case catch reg(S) of {R,[]} -> {ok,R}; @@ -345,6 +358,10 @@ parse(S) -> %% format_error(Error) -> String. +-spec format_error(ErrorDescriptor) -> Chars when + ErrorDescriptor :: errordesc(), + Chars :: io_lib:chars(). + format_error({illegal,What}) -> ["illegal character `",What,"'"]; format_error({unterminated,What}) -> ["unterminated `",What,"'"]; format_error({char_class,What}) -> @@ -353,6 +370,14 @@ format_error({char_class,What}) -> %% -type match(String, RegExp) -> matchres(). %% Find the longest match of RegExp in String. +-spec match(String, RegExp) -> MatchRes when + String :: string(), + RegExp :: string() | regexp(), + MatchRes :: {match, Start, Length} | nomatch | {error, Error}, + Start :: pos_integer(), + Length :: pos_integer(), + Error :: errordesc(). + match(S, RegExp) when is_list(RegExp) -> case parse(RegExp) of {ok,RE} -> match(S, RE); @@ -378,6 +403,14 @@ match(RE, S, St, Pos, L) -> %% -type first_match(String, RegExp) -> matchres(). %% Find the first match of RegExp in String. +-spec first_match(String, RegExp) -> MatchRes when + String :: string(), + RegExp :: string() | regexp(), + MatchRes :: {match, Start, Length} | nomatch | {error, Error}, + Start :: pos_integer(), + Length :: pos_integer(), + Error :: errordesc(). + first_match(S, RegExp) when is_list(RegExp) -> case parse(RegExp) of {ok,RE} -> first_match(S, RE); @@ -400,6 +433,15 @@ first_match(_RE, [], _St) -> nomatch. %% -type matches(String, RegExp) -> {match,[{Start,Length}]} | {error,E}. %% Return the all the non-overlapping matches of RegExp in String. +-spec matches(String, RegExp) -> MatchRes when + String :: string(), + RegExp :: string() | regexp(), + MatchRes :: {match, Matches} | {error, Error}, + Matches :: [{Start, Length}], + Start :: pos_integer(), + Length :: pos_integer(), + Error :: errordesc(). + matches(S, RegExp) when is_list(RegExp) -> case parse(RegExp) of {ok,RE} -> matches(S, RE); @@ -420,6 +462,15 @@ matches(S, RE, St) -> %% the string Replace in String. Accept pre-parsed regular %% expressions. +-spec sub(String, RegExp, New) -> SubRes when + String :: string(), + RegExp :: string() | regexp(), + New :: string(), + NewString :: string(), + SubRes :: {ok, NewString, RepCount} | {error, Error}, + RepCount :: 0 | 1, + Error :: errordesc(). + sub(String, RegExp, Rep) when is_list(RegExp) -> case parse(RegExp) of {ok,RE} -> sub(String, RE, Rep); @@ -449,6 +500,15 @@ sub_repl([], _M, Rest) -> Rest. %% Substitute every match of the regular expression RegExp with the %% string New in String. Accept pre-parsed regular expressions. +-spec gsub(String, RegExp, New) -> SubRes when + String :: string(), + RegExp :: string() | regexp(), + New :: string(), + NewString :: string(), + SubRes :: {ok, NewString, RepCount} | {error, Error}, + RepCount :: non_neg_integer(), + Error :: errordesc(). + gsub(String, RegExp, Rep) when is_list(RegExp) -> case parse(RegExp) of {ok,RE} -> gsub(String, RE, Rep); @@ -462,6 +522,13 @@ gsub(String, RE, Rep) -> %% Split a string into substrings where the RegExp describes the %% field seperator. The RegExp " " is specially treated. +-spec split(String, RegExp) -> SplitRes when + String :: string(), + RegExp :: string() | regexp(), + SplitRes :: {ok, FieldList} | {error, Error}, + FieldList :: [string()], + Error :: errordesc(). + split(String, " ") -> %This is really special {ok,RE} = parse("[ \t]+"), case split_apply(String, RE, true) of diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl index bcddca2567..3fd6c81e5f 100644 --- a/lib/stdlib/src/sets.erl +++ b/lib/stdlib/src/sets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -84,30 +84,38 @@ new() -> %% is_set(Set) -> boolean(). %% Return 'true' if Set is a set of elements, else 'false'. --spec is_set(term()) -> boolean(). +-spec is_set(Set) -> boolean() when + Set :: term(). is_set(#set{}) -> true; is_set(_) -> false. %% size(Set) -> int(). %% Return the number of elements in Set. --spec size(set()) -> non_neg_integer(). +-spec size(Set) -> non_neg_integer() when + Set :: set(). size(S) -> S#set.size. %% to_list(Set) -> [Elem]. %% Return the elements in Set as a list. --spec to_list(set()) -> [term()]. +-spec to_list(Set) -> List when + Set :: set(), + List :: [term()]. to_list(S) -> fold(fun (Elem, List) -> [Elem|List] end, [], S). %% from_list([Elem]) -> Set. %% Build a set from the elements in List. --spec from_list([term()]) -> set(). +-spec from_list(List) -> Set when + List :: [term()], + Set :: set(). from_list(L) -> lists:foldl(fun (E, S) -> add_element(E, S) end, new(), L). %% is_element(Element, Set) -> boolean(). %% Return 'true' if Element is an element of Set, else 'false'. --spec is_element(term(), set()) -> boolean(). +-spec is_element(Element, Set) -> boolean() when + Element :: term(), + Set :: set(). is_element(E, S) -> Slot = get_slot(S, E), Bkt = get_bucket(S, Slot), @@ -115,7 +123,10 @@ is_element(E, S) -> %% add_element(Element, Set) -> Set. %% Return Set with Element inserted in it. --spec add_element(term(), set()) -> set(). +-spec add_element(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: set(), + Set2 :: set(). add_element(E, S0) -> Slot = get_slot(S0, E), {S1,Ic} = on_bucket(fun (B0) -> add_bkt_el(E, B0, B0) end, S0, Slot), @@ -129,7 +140,10 @@ add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}. %% del_element(Element, Set) -> Set. %% Return Set but with Element removed. --spec del_element(term(), set()) -> set(). +-spec del_element(Element, Set1) -> Set2 when + Element :: term(), + Set1 :: set(), + Set2 :: set(). del_element(E, S0) -> Slot = get_slot(S0, E), {S1,Dc} = on_bucket(fun (B0) -> del_bkt_el(E, B0) end, S0, Slot), @@ -144,7 +158,10 @@ del_bkt_el(_, []) -> {[],0}. %% union(Set1, Set2) -> Set %% Return the union of Set1 and Set2. --spec union(set(), set()) -> set(). +-spec union(Set1, Set2) -> Set3 when + Set1 :: set(), + Set2 :: set(), + Set3 :: set(). union(S1, S2) when S1#set.size < S2#set.size -> fold(fun (E, S) -> add_element(E, S) end, S2, S1); union(S1, S2) -> @@ -152,7 +169,9 @@ union(S1, S2) -> %% union([Set]) -> Set %% Return the union of the list of sets. --spec union([set()]) -> set(). +-spec union(SetList) -> Set when + SetList :: [set()], + Set :: set(). union([S1,S2|Ss]) -> union1(union(S1, S2), Ss); union([S]) -> S; @@ -165,7 +184,10 @@ union1(S1, []) -> S1. %% intersection(Set1, Set2) -> Set. %% Return the intersection of Set1 and Set2. --spec intersection(set(), set()) -> set(). +-spec intersection(Set1, Set2) -> Set3 when + Set1 :: set(), + Set2 :: set(), + Set3 :: set(). intersection(S1, S2) when S1#set.size < S2#set.size -> filter(fun (E) -> is_element(E, S2) end, S1); intersection(S1, S2) -> @@ -173,7 +195,9 @@ intersection(S1, S2) -> %% intersection([Set]) -> Set. %% Return the intersection of the list of sets. --spec intersection([set(),...]) -> set(). +-spec intersection(SetList) -> Set when + SetList :: [set(),...], + Set :: set(). intersection([S1,S2|Ss]) -> intersection1(intersection(S1, S2), Ss); intersection([S]) -> S. @@ -185,7 +209,9 @@ intersection1(S1, []) -> S1. %% is_disjoint(Set1, Set2) -> boolean(). %% Check whether Set1 and Set2 are disjoint. --spec is_disjoint(set(), set()) -> boolean(). +-spec is_disjoint(Set1, Set2) -> boolean() when + Set1 :: set(), + Set2 :: set(). is_disjoint(S1, S2) when S1#set.size < S2#set.size -> fold(fun (_, false) -> false; (E, true) -> not is_element(E, S2) @@ -198,25 +224,39 @@ is_disjoint(S1, S2) -> %% subtract(Set1, Set2) -> Set. %% Return all and only the elements of Set1 which are not also in %% Set2. --spec subtract(set(), set()) -> set(). +-spec subtract(Set1, Set2) -> Set3 when + Set1 :: set(), + Set2 :: set(), + Set3 :: set(). subtract(S1, S2) -> filter(fun (E) -> not is_element(E, S2) end, S1). %% is_subset(Set1, Set2) -> boolean(). %% Return 'true' when every element of Set1 is also a member of %% Set2, else 'false'. --spec is_subset(set(), set()) -> boolean(). +-spec is_subset(Set1, Set2) -> boolean() when + Set1 :: set(), + Set2 :: set(). is_subset(S1, S2) -> fold(fun (E, Sub) -> Sub andalso is_element(E, S2) end, true, S1). %% fold(Fun, Accumulator, Set) -> Accumulator. %% Fold function Fun over all elements in Set and return Accumulator. --spec fold(fun((_,_) -> _), T, set()) -> T. +-spec fold(Function, Acc0, Set) -> Acc1 when + Function :: fun((E :: term(),AccIn) -> AccOut), + Set :: set(), + Acc0 :: T, + Acc1 :: T, + AccIn :: T, + AccOut :: T. fold(F, Acc, D) -> fold_set(F, Acc, D). %% filter(Fun, Set) -> Set. %% Filter Set with Fun. --spec filter(fun((_) -> boolean()), set()) -> set(). +-spec filter(Pred, Set1) -> Set2 when + Pred :: fun((E :: term()) -> boolean()), + Set1 :: set(), + Set2 :: set(). filter(F, D) -> filter_set(F, D). %% get_slot(Hashdb, Key) -> Slot. diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index ebb221c151..964697cae6 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -115,7 +115,9 @@ whereis_evaluator(Shell) -> %% Call this function to start a user restricted shell %% from a normal shell session. --spec start_restricted(module()) -> {'error', code:load_error_rsn()}. +-spec start_restricted(Module) -> {'error', Reason} when + Module :: module(), + Reason :: code:load_error_rsn(). start_restricted(RShMod) when is_atom(RShMod) -> case code:ensure_loaded(RShMod) of @@ -465,7 +467,7 @@ getc(N) -> {get({command,N}), get({result,N}), N}. get_cmd(Num, C) -> - case catch erl_eval:expr(Num, []) of + case catch erl_eval:expr(Num, erl_eval:new_bindings()) of {value,N,_} when N < 0 -> getc(C+N); {value,N,_} -> getc(N); _Other -> {undefined,undefined,undefined} @@ -1086,7 +1088,7 @@ shell_default(F,As,Bs) -> end. shell_undef(F,A) -> - erlang:error({shell_undef,F,A}). + erlang:error({shell_undef,F,A,[]}). local_func_handler(Shell, RT, Ef) -> H = fun(Lf) -> @@ -1184,6 +1186,8 @@ expr(E, Bs, Lf, Ef) -> expr_list(Es, Bs, Lf, Ef) -> erl_eval:expr_list(Es, strip_bindings(Bs), Lf, Ef). +-spec strip_bindings(erl_eval:binding_struct()) -> erl_eval:binding_struct(). + strip_bindings(Bs) -> Bs -- [B || {{module,_},_}=B <- Bs]. @@ -1468,23 +1472,26 @@ set_env(App, Name, Val, Default) -> application_controller:set_env(App, Name, Val), Prev. --spec history(non_neg_integer()) -> non_neg_integer(). +-spec history(N) -> non_neg_integer() when + N :: non_neg_integer(). history(L) when is_integer(L), L >= 0 -> set_env(stdlib, shell_history_length, L, ?DEF_HISTORY). --spec results(non_neg_integer()) -> non_neg_integer(). +-spec results(N) -> non_neg_integer() when + N :: non_neg_integer(). results(L) when is_integer(L), L >= 0 -> set_env(stdlib, shell_saved_results, L, ?DEF_RESULTS). --spec catch_exception(boolean()) -> boolean(). +-spec catch_exception(Bool) -> Bool when + Bool :: boolean(). catch_exception(Bool) -> set_env(stdlib, shell_catch_exception, Bool, ?DEF_CATCH_EXCEPTION). --type prompt_func() :: 'default' | {module(),atom()}. --spec prompt_func(prompt_func()) -> prompt_func(). +-spec prompt_func(PromptFunc) -> PromptFunc when + PromptFunc :: 'default' | {module(),atom()}. prompt_func(String) -> set_env(stdlib, shell_prompt_func, String, ?DEF_PROMPT_FUNC). diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index 196b659938..de0179da59 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,6 +54,10 @@ pseudo([Master | ServerList]) -> pseudo(_) -> error_msg("No master node given to slave:pseudo/1~n",[]). +-spec pseudo(Master, ServerList) -> ok when + Master :: node(), + ServerList :: [atom()]. + pseudo(_, []) -> ok; pseudo(Master, [S|Tail]) -> start_pseudo(S, whereis(S), Master), @@ -68,6 +72,9 @@ start_pseudo(_,_,_) -> ok. %% It's already there %% This relay can be used to relay all messages directed to a process. +-spec relay(Pid) -> no_return() when + Pid :: pid(). + relay({badrpc,Reason}) -> error_msg(" ** exiting relay server ~w :~w **~n", [self(),Reason]), exit(Reason); @@ -120,25 +127,61 @@ relay1(Pid) -> %% {error, no_rsh} | %% {error, {already_running, Name@Host}} +-spec start(Host) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. + start(Host) -> L = atom_to_list(node()), Name = upto($@, L), - start(Host, Name). + start(Host, Name, [], no_link). + +-spec start(Host, Name) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Name :: atom(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. start(Host, Name) -> start(Host, Name, []). +-spec start(Host, Name, Args) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Name :: atom(), + Args :: string(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. + start(Host, Name, Args) -> start(Host, Name, Args, no_link). +-spec start_link(Host) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. + start_link(Host) -> L = atom_to_list(node()), Name = upto($@, L), - start_link(Host, Name). + start(Host, Name, [], self()). + +-spec start_link(Host, Name) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Name :: atom(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. start_link(Host, Name) -> start_link(Host, Name, []). +-spec start_link(Host, Name, Args) -> {ok, Node} | {error, Reason} when + Host :: atom(), + Name :: atom(), + Args :: string(), + Node :: node(), + Reason :: timeout | no_rsh | {already_running, Node}. + start_link(Host, Name, Args) -> start(Host, Name, Args, self()). @@ -163,6 +206,9 @@ start(Host0, Name, Args, LinkTo, Prog) -> %% Stops a running node. +-spec stop(Node) -> ok when + Node :: node(). + stop(Node) -> % io:format("stop(~p)~n", [Node]), rpc:call(Node, erlang, halt, []), diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl index a83f803330..34eb224647 100644 --- a/lib/stdlib/src/sofs.erl +++ b/lib/stdlib/src/sofs.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(sofs). @@ -40,11 +40,11 @@ substitution/2, projection/2, partition/1, partition/2, partition/3, multiple_relative_product/2, join/4]). --export([family_to_relation/1, family_specification/2, +-export([family_to_relation/1, family_specification/2, union_of_family/1, intersection_of_family/1, family_union/1, family_intersection/1, family_domain/1, family_range/1, family_field/1, - family_union/2, family_intersection/2, family_difference/2, + family_union/2, family_intersection/2, family_difference/2, partition_family/2, family_projection/2]). -export([family_to_digraph/1, family_to_digraph/2, @@ -64,9 +64,9 @@ -compile({inline, [{external_fun,1},{element_type,1}]}). --compile({inline, +-compile({inline, [{unify_types,2}, {match_types,2}, - {test_rel,3}, {symdiff,3}, + {test_rel,3}, {symdiff,3}, {subst,3}]}). -compile({inline, [{fam_binop,3}]}). @@ -80,13 +80,14 @@ -define(TAG, 'Set'). -define(ORDTAG, 'OrdSet'). --record(?TAG, {data = [], type = type}). --record(?ORDTAG, {orddata = {}, ordtype = type}). +-record(?TAG, {data = [] :: list(), type = type :: term()}). +-record(?ORDTAG, {orddata = {} :: tuple() | atom(), + ordtype = type :: term()}). -define(LIST(S), (S)#?TAG.data). -define(TYPE(S), (S)#?TAG.type). -%%-define(SET(L, T), -%% case is_type(T) of +%%-define(SET(L, T), +%% case is_type(T) of %% true -> #?TAG{data = L, type = T}; %% false -> erlang:error(badtype, [T]) %% end @@ -113,14 +114,40 @@ -define(IS_SET_OF(X), is_list(X)). -define(FAMILY(X, Y), ?BINREL(X, ?SET_OF(Y))). +-export_type([anyset/0, binary_relation/0, external_set/0, a_function/0, + family/0, relation/0, set_of_sets/0, set_fun/0, spec_fun/0, + type/0]). +-export_type([ordset/0, a_set/0]). + +-type(anyset() :: ordset() | a_set()). +-type(binary_relation() :: relation()). +-type(external_set() :: term()). +-type(a_function() :: relation()). +-type(family() :: a_function()). +-opaque(ordset() :: #?ORDTAG{}). +-type(relation() :: a_set()). +-opaque(a_set() :: #?TAG{}). +-type(set_of_sets() :: a_set()). +-type(set_fun() :: pos_integer() + | {external, fun((external_set()) -> external_set())} + | fun((anyset()) -> anyset())). +-type(spec_fun() :: {external, fun((external_set()) -> boolean())} + | fun((anyset()) -> boolean())). +-type(type() :: term()). + +-type(tuple_of(_T) :: tuple()). + %% %% Exported functions %% -%%% +%%% %%% Create sets -%%% +%%% +-spec(from_term(Term) -> AnySet when + AnySet :: anyset(), + Term :: term()). from_term(T) -> Type = case T of _ when is_list(T) -> [?ANYTYPE]; @@ -133,6 +160,10 @@ from_term(T) -> Set end. +-spec(from_term(Term, Type) -> AnySet when + AnySet :: anyset(), + Term :: term(), + Type :: type()). from_term(L, T) -> case is_type(T) of true -> @@ -146,14 +177,23 @@ from_term(L, T) -> erlang:error(badarg, [L, T]) end. +-spec(from_external(ExternalSet, Type) -> AnySet when + ExternalSet :: external_set(), + AnySet :: anyset(), + Type :: type()). from_external(L, ?SET_OF(Type)) -> ?SET(L, Type); from_external(T, Type) -> ?ORDSET(T, Type). +-spec(empty_set() -> Set when + Set :: a_set()). empty_set() -> ?SET([], ?ANYTYPE). +-spec(is_type(Term) -> Bool when + Bool :: boolean(), + Term :: term()). is_type(Atom) when ?IS_ATOM_TYPE(Atom), Atom =/= ?ANYTYPE -> true; is_type(?SET_OF(T)) -> @@ -163,19 +203,26 @@ is_type(T) when tuple_size(T) > 0 -> is_type(_T) -> false. +-spec(set(Terms) -> Set when + Set :: a_set(), + Terms :: [term()]). set(L) -> case catch usort(L) of {'EXIT', _} -> erlang:error(badarg, [L]); - SL -> + SL -> ?SET(SL, ?ATOM_TYPE) end. +-spec(set(Terms, Type) -> Set when + Set :: a_set(), + Terms :: [term()], + Type :: type()). set(L, ?SET_OF(Type) = T) when ?IS_ATOM_TYPE(Type), Type =/= ?ANYTYPE -> case catch usort(L) of {'EXIT', _} -> erlang:error(badarg, [L, T]); - SL -> + SL -> ?SET(SL, Type) end; set(L, ?SET_OF(_) = T) -> @@ -188,6 +235,12 @@ set(L, ?SET_OF(_) = T) -> set(L, T) -> erlang:error(badarg, [L, T]). +-spec(from_sets(ListOfSets) -> Set when + Set :: a_set(), + ListOfSets :: [anyset()]; + (TupleOfSets) -> Ordset when + Ordset :: ordset(), + TupleOfSets :: tuple_of(anyset())). from_sets(Ss) when is_list(Ss) -> case set_of_sets(Ss, [], ?ANYTYPE) of {error, Error} -> @@ -205,6 +258,9 @@ from_sets(Tuple) when is_tuple(Tuple) -> from_sets(T) -> erlang:error(badarg, [T]). +-spec(relation(Tuples) -> Relation when + Relation :: relation(), + Tuples :: [tuple()]). relation([]) -> ?SET([], ?BINREL(?ATOM_TYPE, ?ATOM_TYPE)); relation(Ts = [T | _]) when is_tuple(T) -> @@ -217,6 +273,11 @@ relation(Ts = [T | _]) when is_tuple(T) -> relation(E) -> erlang:error(badarg, [E]). +-spec(relation(Tuples, Type) -> Relation when + N :: integer(), + Type :: N | type(), + Relation :: relation(), + Tuples :: [tuple()]). relation(Ts, TS) -> case catch rel(Ts, TS) of {'EXIT', _} -> @@ -225,6 +286,9 @@ relation(Ts, TS) -> Set end. +-spec(a_function(Tuples) -> Function when + Function :: a_function(), + Tuples :: [tuple()]). a_function(Ts) -> case catch func(Ts, ?BINREL(?ATOM_TYPE, ?ATOM_TYPE)) of {'EXIT', _} -> @@ -235,6 +299,10 @@ a_function(Ts) -> Set end. +-spec(a_function(Tuples, Type) -> Function when + Function :: a_function(), + Tuples :: [tuple()], + Type :: type()). a_function(Ts, T) -> case catch a_func(Ts, T) of {'EXIT', _} -> @@ -245,6 +313,9 @@ a_function(Ts, T) -> Set end. +-spec(family(Tuples) -> Family when + Family :: family(), + Tuples :: [tuple()]). family(Ts) -> case catch fam2(Ts, ?FAMILY(?ATOM_TYPE, ?ATOM_TYPE)) of {'EXIT', _} -> @@ -255,6 +326,10 @@ family(Ts) -> Set end. +-spec(family(Tuples, Type) -> Family when + Family :: family(), + Tuples :: [tuple()], + Type :: type()). family(Ts, T) -> case catch fam(Ts, T) of {'EXIT', _} -> @@ -265,20 +340,30 @@ family(Ts, T) -> Set end. -%%% +%%% %%% Functions on sets. -%%% +%%% +-spec(to_external(AnySet) -> ExternalSet when + ExternalSet :: external_set(), + AnySet :: anyset()). to_external(S) when ?IS_SET(S) -> ?LIST(S); to_external(S) when ?IS_ORDSET(S) -> ?ORDDATA(S). +-spec(type(AnySet) -> Type when + AnySet :: anyset(), + Type :: type()). type(S) when ?IS_SET(S) -> ?SET_OF(?TYPE(S)); type(S) when ?IS_ORDSET(S) -> ?ORDTYPE(S). +-spec(to_sets(ASet) -> Sets when + ASet :: a_set() | ordset(), + Sets :: tuple_of(AnySet) | [AnySet], + AnySet :: anyset()). to_sets(S) when ?IS_SET(S) -> case ?TYPE(S) of ?SET_OF(Type) -> list_of_sets(?LIST(S), Type, []); @@ -289,6 +374,9 @@ to_sets(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) -> to_sets(S) when ?IS_ORDSET(S) -> erlang:error(badarg, [S]). +-spec(no_elements(ASet) -> NoElements when + ASet :: a_set() | ordset(), + NoElements :: non_neg_integer()). no_elements(S) when ?IS_SET(S) -> length(?LIST(S)); no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) -> @@ -296,6 +384,10 @@ no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) -> no_elements(S) when ?IS_ORDSET(S) -> erlang:error(badarg, [S]). +-spec(specification(Fun, Set1) -> Set2 when + Fun :: spec_fun(), + Set1 :: a_set(), + Set2 :: a_set()). specification(Fun, S) when ?IS_SET(S) -> Type = ?TYPE(S), R = case external_fun(Fun) of @@ -311,36 +403,62 @@ specification(Fun, S) when ?IS_SET(S) -> erlang:error(Bad, [Fun, S]) end. +-spec(union(Set1, Set2) -> Set3 when + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). union(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case unify_types(?TYPE(S1), ?TYPE(S2)) of [] -> erlang:error(type_mismatch, [S1, S2]); Type -> ?SET(umerge(?LIST(S1), ?LIST(S2)), Type) end. +-spec(intersection(Set1, Set2) -> Set3 when + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). intersection(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case unify_types(?TYPE(S1), ?TYPE(S2)) of [] -> erlang:error(type_mismatch, [S1, S2]); Type -> ?SET(intersection(?LIST(S1), ?LIST(S2), []), Type) end. +-spec(difference(Set1, Set2) -> Set3 when + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). difference(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case unify_types(?TYPE(S1), ?TYPE(S2)) of [] -> erlang:error(type_mismatch, [S1, S2]); Type -> ?SET(difference(?LIST(S1), ?LIST(S2), []), Type) end. +-spec(symdiff(Set1, Set2) -> Set3 when + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). symdiff(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case unify_types(?TYPE(S1), ?TYPE(S2)) of [] -> erlang:error(type_mismatch, [S1, S2]); Type -> ?SET(symdiff(?LIST(S1), ?LIST(S2), []), Type) end. +-spec(symmetric_partition(Set1, Set2) -> {Set3, Set4, Set5} when + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set(), + Set4 :: a_set(), + Set5 :: a_set()). symmetric_partition(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case unify_types(?TYPE(S1), ?TYPE(S2)) of [] -> erlang:error(type_mismatch, [S1, S2]); Type -> sympart(?LIST(S1), ?LIST(S2), [], [], [], Type) end. +-spec(product(Set1, Set2) -> BinRel when + BinRel :: binary_relation(), + Set1 :: a_set(), + Set2 :: a_set()). product(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> if ?TYPE(S1) =:= ?ANYTYPE -> S1; @@ -351,6 +469,9 @@ product(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> ?SET(relprod(map(F, ?LIST(S1)), map(F, ?LIST(S2))), T) end. +-spec(product(TupleOfSets) -> Relation when + Relation :: relation(), + TupleOfSets :: tuple_of(a_set())). product({S1, S2}) -> product(S1, S2); product(T) when is_tuple(T) -> @@ -365,11 +486,15 @@ product(T) when is_tuple(T) -> case member([], L) of true -> empty_set(); - false -> + false -> ?SET(reverse(prod(L, [], [])), Type) end end. +-spec(constant_function(Set, AnySet) -> Function when + AnySet :: anyset(), + Function :: a_function(), + Set :: a_set()). constant_function(S, E) when ?IS_SET(S) -> case {?TYPE(S), is_sofs_set(E)} of {?ANYTYPE, true} -> S; @@ -381,6 +506,10 @@ constant_function(S, E) when ?IS_SET(S) -> constant_function(S, E) when ?IS_ORDSET(S) -> erlang:error(badarg, [S, E]). +-spec(is_equal(AnySet1, AnySet2) -> Bool when + AnySet1 :: anyset(), + AnySet2 :: anyset(), + Bool :: boolean()). is_equal(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case match_types(?TYPE(S1), ?TYPE(S2)) of true -> ?LIST(S1) == ?LIST(S2); @@ -396,12 +525,19 @@ is_equal(S1, S2) when ?IS_SET(S1), ?IS_ORDSET(S2) -> is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_SET(S2) -> erlang:error(type_mismatch, [S1, S2]). +-spec(is_subset(Set1, Set2) -> Bool when + Bool :: boolean(), + Set1 :: a_set(), + Set2 :: a_set()). is_subset(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case match_types(?TYPE(S1), ?TYPE(S2)) of true -> subset(?LIST(S1), ?LIST(S2)); false -> erlang:error(type_mismatch, [S1, S2]) end. +-spec(is_sofs_set(Term) -> Bool when + Bool :: boolean(), + Term :: term()). is_sofs_set(S) when ?IS_SET(S) -> true; is_sofs_set(S) when ?IS_ORDSET(S) -> @@ -409,16 +545,26 @@ is_sofs_set(S) when ?IS_ORDSET(S) -> is_sofs_set(_S) -> false. +-spec(is_set(AnySet) -> Bool when + AnySet :: anyset(), + Bool :: boolean()). is_set(S) when ?IS_SET(S) -> true; is_set(S) when ?IS_ORDSET(S) -> false. -is_empty_set(S) when ?IS_SET(S) -> +-spec(is_empty_set(AnySet) -> Bool when + AnySet :: anyset(), + Bool :: boolean()). +is_empty_set(S) when ?IS_SET(S) -> ?LIST(S) =:= []; is_empty_set(S) when ?IS_ORDSET(S) -> false. +-spec(is_disjoint(Set1, Set2) -> Bool when + Bool :: boolean(), + Set1 :: a_set(), + Set2 :: a_set()). is_disjoint(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> case match_types(?TYPE(S1), ?TYPE(S2)) of true -> @@ -433,6 +579,9 @@ is_disjoint(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> %%% Functions on set-of-sets. %%% +-spec(union(SetOfSets) -> Set when + Set :: a_set(), + SetOfSets :: set_of_sets()). union(Sets) when ?IS_SET(Sets) -> case ?TYPE(Sets) of ?SET_OF(Type) -> ?SET(lunion(?LIST(Sets)), Type); @@ -440,6 +589,9 @@ union(Sets) when ?IS_SET(Sets) -> _ -> erlang:error(badarg, [Sets]) end. +-spec(intersection(SetOfSets) -> Set when + Set :: a_set(), + SetOfSets :: set_of_sets()). intersection(Sets) when ?IS_SET(Sets) -> case ?LIST(Sets) of [] -> erlang:error(badarg, [Sets]); @@ -451,32 +603,41 @@ intersection(Sets) when ?IS_SET(Sets) -> end end. +-spec(canonical_relation(SetOfSets) -> BinRel when + BinRel :: binary_relation(), + SetOfSets :: set_of_sets()). canonical_relation(Sets) when ?IS_SET(Sets) -> ST = ?TYPE(Sets), case ST of ?SET_OF(?ANYTYPE) -> empty_set(); - ?SET_OF(Type) -> + ?SET_OF(Type) -> ?SET(can_rel(?LIST(Sets), []), ?BINREL(Type, ST)); ?ANYTYPE -> Sets; _ -> erlang:error(badarg, [Sets]) end. -%%% +%%% %%% Functions on binary relations only. -%%% +%%% rel2fam(R) -> relation_to_family(R). +-spec(relation_to_family(BinRel) -> Family when + Family :: family(), + BinRel :: binary_relation()). %% Inlined. relation_to_family(R) when ?IS_SET(R) -> case ?TYPE(R) of - ?BINREL(DT, RT) -> + ?BINREL(DT, RT) -> ?SET(rel2family(?LIST(R)), ?FAMILY(DT, RT)); ?ANYTYPE -> R; _Else -> erlang:error(badarg, [R]) end. +-spec(domain(BinRel) -> Set when + BinRel :: binary_relation(), + Set :: a_set()). domain(R) when ?IS_SET(R) -> case ?TYPE(R) of ?BINREL(DT, _) -> ?SET(dom(?LIST(R)), DT); @@ -484,6 +645,9 @@ domain(R) when ?IS_SET(R) -> _Else -> erlang:error(badarg, [R]) end. +-spec(range(BinRel) -> Set when + BinRel :: binary_relation(), + Set :: a_set()). range(R) when ?IS_SET(R) -> case ?TYPE(R) of ?BINREL(_, RT) -> ?SET(ran(?LIST(R), []), RT); @@ -491,35 +655,63 @@ range(R) when ?IS_SET(R) -> _ -> erlang:error(badarg, [R]) end. +-spec(field(BinRel) -> Set when + BinRel :: binary_relation(), + Set :: a_set()). %% In "Introduction to LOGIC", Suppes defines the field of a binary %% relation to be the union of the domain and the range (or %% counterdomain). field(R) -> union(domain(R), range(R)). +-spec(relative_product(ListOfBinRels) -> BinRel2 when + ListOfBinRels :: [BinRel, ...], + BinRel :: binary_relation(), + BinRel2 :: binary_relation()). +%% The following clause is kept for backward compatibility. +%% The list is due to Dialyzer's specs. relative_product(RT) when is_tuple(RT) -> - case relprod_n(RT, foo, false, false) of - {error, Reason} -> - erlang:error(Reason, [RT]); + relative_product(tuple_to_list(RT)); +relative_product(RL) when is_list(RL) -> + case relprod_n(RL, foo, false, false) of + {error, Reason} -> + erlang:error(Reason, [RL]); Reply -> Reply end. +-spec(relative_product(ListOfBinRels, BinRel1) -> BinRel2 when + ListOfBinRels :: [BinRel, ...], + BinRel :: binary_relation(), + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(); + (BinRel1, BinRel2) -> BinRel3 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(), + BinRel3 :: binary_relation()). relative_product(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) -> relative_product1(converse(R1), R2); +%% The following clause is kept for backward compatibility. +%% The list is due to Dialyzer's specs. relative_product(RT, R) when is_tuple(RT), ?IS_SET(R) -> + relative_product(tuple_to_list(RT), R); +relative_product(RL, R) when is_list(RL), ?IS_SET(R) -> EmptyR = case ?TYPE(R) of ?BINREL(_, _) -> ?LIST(R) =:= []; ?ANYTYPE -> true; - _ -> erlang:error(badarg, [RT, R]) + _ -> erlang:error(badarg, [RL, R]) end, - case relprod_n(RT, R, EmptyR, true) of - {error, Reason} -> - erlang:error(Reason, [RT, R]); + case relprod_n(RL, R, EmptyR, true) of + {error, Reason} -> + erlang:error(Reason, [RL, R]); Reply -> Reply end. +-spec(relative_product1(BinRel1, BinRel2) -> BinRel3 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(), + BinRel3 :: binary_relation()). relative_product1(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) -> {DTR1, RTR1} = case ?TYPE(R1) of ?BINREL(_, _) = R1T -> R1T; @@ -538,16 +730,23 @@ relative_product1(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) -> false -> erlang:error(type_mismatch, [R1, R2]) end. +-spec(converse(BinRel1) -> BinRel2 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation()). converse(R) when ?IS_SET(R) -> case ?TYPE(R) of ?BINREL(DT, RT) -> ?SET(converse(?LIST(R), []), ?BINREL(RT, DT)); ?ANYTYPE -> R; _ -> erlang:error(badarg, [R]) end. - + +-spec(image(BinRel, Set1) -> Set2 when + BinRel :: binary_relation(), + Set1 :: a_set(), + Set2 :: a_set()). image(R, S) when ?IS_SET(R), ?IS_SET(S) -> case ?TYPE(R) of - ?BINREL(DT, RT) -> + ?BINREL(DT, RT) -> case match_types(DT, ?TYPE(S)) of true -> ?SET(usort(restrict(?LIST(S), ?LIST(R))), RT); @@ -558,9 +757,13 @@ image(R, S) when ?IS_SET(R), ?IS_SET(S) -> _ -> erlang:error(badarg, [R, S]) end. +-spec(inverse_image(BinRel, Set1) -> Set2 when + BinRel :: binary_relation(), + Set1 :: a_set(), + Set2 :: a_set()). inverse_image(R, S) when ?IS_SET(R), ?IS_SET(S) -> case ?TYPE(R) of - ?BINREL(DT, RT) -> + ?BINREL(DT, RT) -> case match_types(RT, ?TYPE(S)) of true -> NL = restrict(?LIST(S), converse(?LIST(R), [])), @@ -572,17 +775,23 @@ inverse_image(R, S) when ?IS_SET(R), ?IS_SET(S) -> _ -> erlang:error(badarg, [R, S]) end. +-spec(strict_relation(BinRel1) -> BinRel2 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation()). strict_relation(R) when ?IS_SET(R) -> case ?TYPE(R) of - Type = ?BINREL(_, _) -> + Type = ?BINREL(_, _) -> ?SET(strict(?LIST(R), []), Type); ?ANYTYPE -> R; _ -> erlang:error(badarg, [R]) end. - + +-spec(weak_relation(BinRel1) -> BinRel2 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation()). weak_relation(R) when ?IS_SET(R) -> case ?TYPE(R) of - ?BINREL(DT, RT) -> + ?BINREL(DT, RT) -> case unify_types(DT, RT) of [] -> erlang:error(badarg, [R]); @@ -592,7 +801,12 @@ weak_relation(R) when ?IS_SET(R) -> ?ANYTYPE -> R; _ -> erlang:error(badarg, [R]) end. - + +-spec(extension(BinRel1, Set, AnySet) -> BinRel2 when + AnySet :: anyset(), + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(), + Set :: a_set()). extension(R, S, E) when ?IS_SET(R), ?IS_SET(S) -> case {?TYPE(R), ?TYPE(S), is_sofs_set(E)} of {T=?BINREL(DT, RT), ST, true} -> @@ -621,9 +835,12 @@ extension(R, S, E) when ?IS_SET(R), ?IS_SET(S) -> erlang:error(badarg, [R, S, E]) end. +-spec(is_a_function(BinRel) -> Bool when + Bool :: boolean(), + BinRel :: binary_relation()). is_a_function(R) when ?IS_SET(R) -> case ?TYPE(R) of - ?BINREL(_, _) -> + ?BINREL(_, _) -> case ?LIST(R) of [] -> true; [{V,_} | Es] -> is_a_func(Es, V) @@ -632,16 +849,28 @@ is_a_function(R) when ?IS_SET(R) -> _ -> erlang:error(badarg, [R]) end. +-spec(restriction(BinRel1, Set) -> BinRel2 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(), + Set :: a_set()). restriction(Relation, Set) -> restriction(1, Relation, Set). +-spec(drestriction(BinRel1, Set) -> BinRel2 when + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation(), + Set :: a_set()). drestriction(Relation, Set) -> drestriction(1, Relation, Set). -%%% +%%% %%% Functions on functions only. -%%% +%%% +-spec(composite(Function1, Function2) -> Function3 when + Function1 :: a_function(), + Function2 :: a_function(), + Function3 :: a_function()). composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) -> ?BINREL(DTF1, RTF1) = case ?TYPE(Fn1)of ?BINREL(_, _) = F1T -> F1T; @@ -656,7 +885,7 @@ composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) -> case match_types(RTF1, DTF2) of true when DTF1 =:= ?ANYTYPE -> Fn1; true when DTF2 =:= ?ANYTYPE -> Fn2; - true -> + true -> case comp(?LIST(Fn1), ?LIST(Fn2)) of SL when is_list(SL) -> ?SET(sort(SL), ?BINREL(DTF1, RTF2)); @@ -666,9 +895,12 @@ composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) -> false -> erlang:error(type_mismatch, [Fn1, Fn2]) end. +-spec(inverse(Function1) -> Function2 when + Function1 :: a_function(), + Function2 :: a_function()). inverse(Fn) when ?IS_SET(Fn) -> case ?TYPE(Fn) of - ?BINREL(DT, RT) -> + ?BINREL(DT, RT) -> case inverse1(?LIST(Fn)) of SL when is_list(SL) -> ?SET(SL, ?BINREL(RT, DT)); @@ -678,11 +910,16 @@ inverse(Fn) when ?IS_SET(Fn) -> ?ANYTYPE -> Fn; _ -> erlang:error(badarg, [Fn]) end. - -%%% + +%%% %%% Functions on relations (binary or other). -%%% +%%% +-spec(restriction(SetFun, Set1, Set2) -> Set3 when + SetFun :: set_fun(), + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). %% Equivalent to range(restriction(inverse(substitution(Fun, S1)), S2)). restriction(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) -> RT = ?TYPE(R), @@ -747,6 +984,11 @@ restriction(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> end end. +-spec(drestriction(SetFun, Set1, Set2) -> Set3 when + SetFun :: set_fun(), + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set()). drestriction(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) -> RT = ?TYPE(R), ST = ?TYPE(S), @@ -812,6 +1054,10 @@ drestriction(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> end end. +-spec(projection(SetFun, Set1) -> Set2 when + SetFun :: set_fun(), + Set1 :: a_set(), + Set2 :: a_set()). projection(I, Set) when is_integer(I), ?IS_SET(Set) -> Type = ?TYPE(Set), case check_for_sort(Type, I) of @@ -827,6 +1073,10 @@ projection(I, Set) when is_integer(I), ?IS_SET(Set) -> projection(Fun, Set) -> range(substitution(Fun, Set)). +-spec(substitution(SetFun, Set1) -> Set2 when + SetFun :: set_fun(), + Set1 :: a_set(), + Set2 :: a_set()). substitution(I, Set) when is_integer(I), ?IS_SET(Set) -> Type = ?TYPE(Set), case check_for_sort(Type, I) of @@ -867,11 +1117,18 @@ substitution(SetFun, Set) when ?IS_SET(Set) -> end end. +-spec(partition(SetOfSets) -> Partition when + SetOfSets :: set_of_sets(), + Partition :: a_set()). partition(Sets) -> F1 = relation_to_family(canonical_relation(Sets)), F2 = relation_to_family(converse(F1)), range(F2). +-spec(partition(SetFun, Set) -> Partition when + SetFun :: set_fun(), + Partition :: a_set(), + Set :: a_set()). partition(I, Set) when is_integer(I), ?IS_SET(Set) -> Type = ?TYPE(Set), case check_for_sort(Type, I) of @@ -887,6 +1144,12 @@ partition(I, Set) when is_integer(I), ?IS_SET(Set) -> partition(Fun, Set) -> range(partition_family(Fun, Set)). +-spec(partition(SetFun, Set1, Set2) -> {Set3, Set4} when + SetFun :: set_fun(), + Set1 :: a_set(), + Set2 :: a_set(), + Set3 :: a_set(), + Set4 :: a_set()). partition(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) -> RT = ?TYPE(R), ST = ?TYPE(S), @@ -954,21 +1217,32 @@ partition(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) -> end end. +-spec(multiple_relative_product(TupleOfBinRels, BinRel1) -> BinRel2 when + TupleOfBinRels :: tuple_of(BinRel), + BinRel :: binary_relation(), + BinRel1 :: binary_relation(), + BinRel2 :: binary_relation()). multiple_relative_product(T, R) when is_tuple(T), ?IS_SET(R) -> case test_rel(R, tuple_size(T), eq) of true when ?TYPE(R) =:= ?ANYTYPE -> empty_set(); - true -> + true -> MProd = mul_relprod(tuple_to_list(T), 1, R), - relative_product(list_to_tuple(MProd)); - false -> + relative_product(MProd); + false -> erlang:error(badarg, [T, R]) end. -join(R1, I1, R2, I2) +-spec(join(Relation1, I, Relation2, J) -> Relation3 when + Relation1 :: relation(), + Relation2 :: relation(), + Relation3 :: relation(), + I :: pos_integer(), + J :: pos_integer()). +join(R1, I1, R2, I2) when ?IS_SET(R1), ?IS_SET(R2), is_integer(I1), is_integer(I2) -> case test_rel(R1, I1, lte) and test_rel(R2, I2, lte) of - false -> + false -> erlang:error(badarg, [R1, I1, R2, I2]); true when ?TYPE(R1) =:= ?ANYTYPE -> R1; true when ?TYPE(R2) =:= ?ANYTYPE -> R2; @@ -980,8 +1254,8 @@ join(R1, I1, R2, I2) true -> fun({X,Y}) -> join_element(X, Y) end; false -> - fun({X,Y}) -> - list_to_tuple(join_element(X, Y, I2)) + fun({X,Y}) -> + list_to_tuple(join_element(X, Y, I2)) end end, ?SET(replace(T, F, []), F({?TYPE(R1), ?TYPE(R2)})) @@ -1001,9 +1275,15 @@ test_rel(R, I, C) -> %%% Family functions %%% +-spec(fam2rel(Family) -> BinRel when + Family :: family(), + BinRel :: binary_relation()). fam2rel(F) -> family_to_relation(F). +-spec(family_to_relation(Family) -> BinRel when + Family :: family(), + BinRel :: binary_relation()). %% Inlined. family_to_relation(F) when ?IS_SET(F) -> case ?TYPE(F) of @@ -1013,6 +1293,10 @@ family_to_relation(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_specification(Fun, Family1) -> Family2 when + Fun :: spec_fun(), + Family1 :: family(), + Family2 :: family()). family_specification(Fun, F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(_DT, Type) = FType -> @@ -1032,6 +1316,9 @@ family_specification(Fun, F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [Fun, F]) end. +-spec(union_of_family(Family) -> Set when + Family :: family(), + Set :: a_set()). union_of_family(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(_DT, Type) -> @@ -1040,6 +1327,9 @@ union_of_family(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(intersection_of_family(Family) -> Set when + Family :: family(), + Set :: a_set()). intersection_of_family(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(_DT, Type) -> @@ -1052,6 +1342,9 @@ intersection_of_family(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_union(Family1) -> Family2 when + Family1 :: family(), + Family2 :: family()). family_union(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(DT, ?SET_OF(Type)) -> @@ -1060,6 +1353,9 @@ family_union(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_intersection(Family1) -> Family2 when + Family1 :: family(), + Family2 :: family()). family_intersection(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(DT, ?SET_OF(Type)) -> @@ -1073,6 +1369,9 @@ family_intersection(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_domain(Family1) -> Family2 when + Family1 :: family(), + Family2 :: family()). family_domain(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(FDT, ?BINREL(DT, _)) -> @@ -1082,6 +1381,9 @@ family_domain(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_range(Family1) -> Family2 when + Family1 :: family(), + Family2 :: family()). family_range(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(DT, ?BINREL(_, RT)) -> @@ -1091,15 +1393,30 @@ family_range(F) when ?IS_SET(F) -> _ -> erlang:error(badarg, [F]) end. +-spec(family_field(Family1) -> Family2 when + Family1 :: family(), + Family2 :: family()). family_field(F) -> family_union(family_domain(F), family_range(F)). +-spec(family_union(Family1, Family2) -> Family3 when + Family1 :: family(), + Family2 :: family(), + Family3 :: family()). family_union(F1, F2) -> fam_binop(F1, F2, fun fam_union/3). +-spec(family_intersection(Family1, Family2) -> Family3 when + Family1 :: family(), + Family2 :: family(), + Family3 :: family()). family_intersection(F1, F2) -> fam_binop(F1, F2, fun fam_intersect/3). +-spec(family_difference(Family1, Family2) -> Family3 when + Family1 :: family(), + Family2 :: family(), + Family3 :: family()). family_difference(F1, F2) -> fam_binop(F1, F2, fun fam_difference/3). @@ -1108,13 +1425,17 @@ fam_binop(F1, F2, FF) when ?IS_SET(F1), ?IS_SET(F2) -> case unify_types(?TYPE(F1), ?TYPE(F2)) of [] -> erlang:error(type_mismatch, [F1, F2]); - ?ANYTYPE -> + ?ANYTYPE -> F1; - Type = ?FAMILY(_, _) -> + Type = ?FAMILY(_, _) -> ?SET(FF(?LIST(F1), ?LIST(F2), []), Type); _ -> erlang:error(badarg, [F1, F2]) end. +-spec(partition_family(SetFun, Set) -> Family when + Family :: family(), + SetFun :: set_fun(), + Set :: a_set()). partition_family(I, Set) when is_integer(I), ?IS_SET(Set) -> Type = ?TYPE(Set), case check_for_sort(Type, I) of @@ -1159,8 +1480,12 @@ partition_family(SetFun, Set) when ?IS_SET(Set) -> end end. +-spec(family_projection(SetFun, Family1) -> Family2 when + SetFun :: set_fun(), + Family1 :: family(), + Family2 :: family()). family_projection(SetFun, F) when ?IS_SET(F) -> - case ?TYPE(F) of + case ?TYPE(F) of ?FAMILY(_, _) when [] =:= ?LIST(F) -> empty_set(); ?FAMILY(DT, Type) -> @@ -1172,7 +1497,7 @@ family_projection(SetFun, F) when ?IS_SET(F) -> Bad -> erlang:error(Bad, [SetFun, F]) end; - _ -> + _ -> erlang:error(badarg, [SetFun, F]) end; ?ANYTYPE -> F; @@ -1183,6 +1508,9 @@ family_projection(SetFun, F) when ?IS_SET(F) -> %%% Digraph functions %%% +-spec(family_to_digraph(Family) -> Graph when + Graph :: digraph(), + Family :: family()). family_to_digraph(F) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(_, _) -> fam2digraph(F, digraph:new()); @@ -1190,6 +1518,10 @@ family_to_digraph(F) when ?IS_SET(F) -> _Else -> erlang:error(badarg, [F]) end. +-spec(family_to_digraph(Family, GraphType) -> Graph when + Graph :: digraph(), + Family :: family(), + GraphType :: [digraph:d_type()]). family_to_digraph(F, Type) when ?IS_SET(F) -> case ?TYPE(F) of ?FAMILY(_, _) -> ok; @@ -1208,12 +1540,19 @@ family_to_digraph(F, Type) when ?IS_SET(F) -> error:badarg -> erlang:error(badarg, [F, Type]) end. +-spec(digraph_to_family(Graph) -> Family when + Graph :: digraph(), + Family :: family()). digraph_to_family(G) -> case catch digraph_family(G) of {'EXIT', _} -> erlang:error(badarg, [G]); L -> ?SET(L, ?FAMILY(?ATOM_TYPE, ?ATOM_TYPE)) end. +-spec(digraph_to_family(Graph, Type) -> Family when + Graph :: digraph(), + Family :: family(), + Type :: type()). digraph_to_family(G, T) -> case {is_type(T), T} of {true, ?SET_OF(?FAMILY(_,_) = Type)} -> @@ -1284,7 +1623,7 @@ rel(Ts, [Type]) -> end; rel(Ts, Sz) -> rel(Ts, Sz, erlang:make_tuple(Sz, ?ATOM_TYPE)). - + atoms_only(Type, I) when ?IS_ATOM_TYPE(?REL_TYPE(I, Type)) -> atoms_only(Type, I+1); atoms_only(Type, I) when I > tuple_size(Type), ?IS_RELATION(Type) -> @@ -1312,7 +1651,7 @@ rel_type([], SL, Type) when ?IS_RELATION(Type) -> %% Inlined. a_func(Ts, T) -> case {T, is_type(T)} of - {[?BINREL(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT), + {[?BINREL(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT), ?IS_ATOM_TYPE(RT) -> func(Ts, Type); {[Type], true} -> @@ -1333,16 +1672,16 @@ func([], _X0, L, Type) -> %% Inlined. fam(Ts, T) -> case {T, is_type(T)} of - {[?FAMILY(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT), + {[?FAMILY(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT), ?IS_ATOM_TYPE(RT) -> fam2(Ts, Type); {[Type], true} -> func_type(Ts, [], Type, fun(?FAMILY(_,_)) -> true end) end. -fam2([], Type) -> +fam2([], Type) -> ?SET([], Type); -fam2(Ts, Type) -> +fam2(Ts, Type) -> fam2(sort(Ts), Ts, [], Type). fam2([{I,L} | T], I0, SL, Type) when I /= I0 -> @@ -1383,7 +1722,7 @@ setify(E, Type0) -> {Type, OrdSet} = make_element(E, Type0, Type0), ?ORDSET(OrdSet, Type). -is_no_lists(T) when is_tuple(T) -> +is_no_lists(T) when is_tuple(T) -> Sz = tuple_size(T), is_no_lists(T, Sz, Sz, []). @@ -1404,7 +1743,7 @@ create([], T, _T0, L) -> make_element(C, ?ANYTYPE, _T0) -> make_element(C); -make_element(C, Atom, ?ANYTYPE) when ?IS_ATOM_TYPE(Atom), +make_element(C, Atom, ?ANYTYPE) when ?IS_ATOM_TYPE(Atom), not is_list(C), not is_tuple(C) -> {Atom, C}; make_element(C, Atom, Atom) when ?IS_ATOM_TYPE(Atom) -> @@ -1585,12 +1924,12 @@ sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) when H1 == H2 -> sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) -> sympart2(T1, T2, L1, L12, [H2 | L2], T, H1); sympart(S1, [], L1, L12, L2, T) -> - {?SET(reverse(L1, S1), T), - ?SET(reverse(L12), T), + {?SET(reverse(L1, S1), T), + ?SET(reverse(L12), T), ?SET(reverse(L2), T)}; sympart(_, S2, L1, L12, L2, T) -> - {?SET(reverse(L1), T), - ?SET(reverse(L12), T), + {?SET(reverse(L1), T), + ?SET(reverse(L12), T), ?SET(reverse(L2, S2), T)}. sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 < H2 -> @@ -1600,8 +1939,8 @@ sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 == H2 -> sympart1([H1 | T1], T2, L1, L12, L2, T, H2) -> sympart2(T1, T2, L1, L12, [H2 | L2], T, H1); sympart1(_, T2, L1, L12, L2, T, H2) -> - {?SET(reverse(L1), T), - ?SET(reverse(L12), T), + {?SET(reverse(L1), T), + ?SET(reverse(L12), T), ?SET(reverse(L2, [H2 | T2]), T)}. sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 > H2 -> @@ -1611,8 +1950,8 @@ sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 == H2 -> sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) -> sympart1(T1, T2, [H1 | L1], L12, L2, T, H2); sympart2(T1, _, L1, L12, L2, T, H1) -> - {?SET(reverse(L1, [H1 | T1]), T), - ?SET(reverse(L12), T), + {?SET(reverse(L1, [H1 | T1]), T), + ?SET(reverse(L12), T), ?SET(reverse(L2), T)}. prod([[E | Es] | Xs], T, L) -> @@ -1660,7 +1999,7 @@ lunion([[] | Ls]) -> lunion(Ls); lunion([S | Ss]) -> umerge(lunion(Ss, last(S), [S], [])); -lunion([]) -> +lunion([]) -> []. lunion([[E] = S | Ss], Last, SL, Ls) when E > Last -> % optimization @@ -1669,7 +2008,7 @@ lunion([S | Ss], Last, SL, Ls) when hd(S) > Last -> lunion(Ss, last(S), [S | SL], Ls); lunion([S | Ss], _Last, SL, Ls) -> lunion(Ss, last(S), [S], [append(reverse(SL)) | Ls]); -lunion([], _Last, SL, Ls) -> +lunion([], _Last, SL, Ls) -> [append(reverse(SL)) | Ls]. %% The empty list is always the first list, if present. @@ -1752,18 +2091,17 @@ relprod(B0, Bx0, By0, A0, L, Ax, [{Bx,By} | B], Ay) when Ay == Bx -> relprod(B0, Bx0, By0, A0, L, _Ax, _B, _Ay) -> relprod2(B0, Bx0, By0, A0, L). -relprod_n({}, _R, _EmptyG, _IsR) -> +relprod_n([], _R, _EmptyG, _IsR) -> {error, badarg}; -relprod_n(RT, R, EmptyR, IsR) -> - RL = tuple_to_list(RT), +relprod_n(RL, R, EmptyR, IsR) -> case domain_type(RL, ?ANYTYPE) of - Error = {error, _Reason} -> + Error = {error, _Reason} -> Error; DType -> Empty = any(fun is_empty_set/1, RL) or EmptyR, RType = range_type(RL, []), Type = ?BINREL(DType, RType), - Prod = + Prod = case Empty of true when DType =:= ?ANYTYPE; RType =:= ?ANYTYPE -> empty_set(); @@ -1771,7 +2109,7 @@ relprod_n(RT, R, EmptyR, IsR) -> ?SET([], Type); false -> TL = ?LIST((relprod_n(RL))), - Sz = tuple_size(RT), + Sz = length(RL), Fun = fun({X,A}) -> {X, flat(Sz, A, [])} end, ?SET(map(Fun, TL), Type) end, @@ -1799,12 +2137,12 @@ flat(N, {T,A}, L) -> domain_type([T | Ts], T0) when ?IS_SET(T) -> case ?TYPE(T) of - ?BINREL(DT, _RT) -> + ?BINREL(DT, _RT) -> case unify_types(DT, T0) of [] -> {error, type_mismatch}; T1 -> domain_type(Ts, T1) end; - ?ANYTYPE -> + ?ANYTYPE -> domain_type(Ts, T0); _ -> {error, badarg} end; @@ -1813,12 +2151,12 @@ domain_type([], T0) -> range_type([T | Ts], L) -> case ?TYPE(T) of - ?BINREL(_DT, RT) -> + ?BINREL(_DT, RT) -> range_type(Ts, [RT | L]); - ?ANYTYPE -> + ?ANYTYPE -> ?ANYTYPE end; -range_type([], L) -> +range_type([], L) -> list_to_tuple(reverse(L)). converse([{A,B} | X], L) -> @@ -1861,7 +2199,7 @@ weak1([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < Y weak1(Es, Ys, L, X) -> weak(Es, Ys, [{X,X} | L]). -weak2([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < _Y +weak2([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < _Y weak2(Es, Ys, [E | L], X); weak2(Es, Ys, L, _X) -> weak(Es, Ys, L). @@ -1910,7 +2248,7 @@ restrict_n(I, [T | Ts], Key, Keys, L) -> end; restrict_n(_I, _Ts, _Key, _Keys, L) -> L. - + restrict_n(I, K, Ts, [Key | Keys], L, E) when K > Key -> restrict_n(I, K, Ts, Keys, L, E); restrict_n(I, K, Ts, [Key | Keys], L, E) when K == Key -> @@ -1933,7 +2271,7 @@ restrict([{K,E} | Ts], _Key, Keys, L) -> restrict(Ts, K, Keys, L, E); restrict(_Ts, _Key, _Keys, L) -> L. - + restrict(Ts, K, [Key | Keys], L, E) when K > Key -> restrict(Ts, K, Keys, L, E); restrict(Ts, K, [Key | Keys], L, E) when K == Key -> @@ -1956,7 +2294,7 @@ diff_restrict_n(I, _Ts, _Key, _Keys, L) when I =:= 1 -> reverse(L); diff_restrict_n(_I, _Ts, _Key, _Keys, L) -> sort(L). - + diff_restrict_n(I, K, Ts, [Key | Keys], L, T) when K > Key -> diff_restrict_n(I, K, Ts, Keys, L, T); diff_restrict_n(I, K, Ts, [Key | Keys], L, _T) when K == Key -> @@ -1981,7 +2319,7 @@ diff_restrict([{K,E} | Ts], _Key, Keys, L) -> diff_restrict(Ts, K, Keys, L, E); diff_restrict(_Ts, _Key, _Keys, L) -> L. - + diff_restrict(Ts, K, [Key | Keys], L, E) when K > Key -> diff_restrict(Ts, K, Keys, L, E); diff_restrict(Ts, K, [Key | Keys], L, _E) when K == Key -> @@ -2041,7 +2379,7 @@ external_fun({external, Function}) when is_atom(Function) -> false; external_fun({external, Fun}) -> Fun; -external_fun(_) -> +external_fun(_) -> false. %% Inlined. @@ -2121,7 +2459,7 @@ partition3_n(I, _Ts, _Key, _Keys, L1, L2) when I =:= 1 -> [reverse(L1) | reverse(L2)]; partition3_n(_I, _Ts, _Key, _Keys, L1, L2) -> [sort(L1) | sort(L2)]. - + partition3_n(I, K, Ts, [Key | Keys], L1, L2, T) when K > Key -> partition3_n(I, K, Ts, Keys, L1, L2, T); partition3_n(I, K, Ts, [Key | Keys], L1, L2, T) when K == Key -> @@ -2146,7 +2484,7 @@ partition3([{K,E} | Ts], _Key, Keys, L1, L2) -> partition3(Ts, K, Keys, L1, L2, E); partition3(_Ts, _Key, _Keys, L1, L2) -> [L1 | L2]. - + partition3(Ts, K, [Key | Keys], L1, L2, E) when K > Key -> partition3(Ts, K, Keys, L1, L2, E); partition3(Ts, K, [Key | Keys], L1, L2, E) when K == Key -> @@ -2192,7 +2530,7 @@ join_element(E1, E2, I2) -> join_element2([B | Bs], C, I2) when C =/= I2 -> [B | join_element2(Bs, C+1, I2)]; -join_element2([_ | Bs], _C, _I2) -> +join_element2([_ | Bs], _C, _I2) -> Bs. family2rel([{X,S} | F], L) -> @@ -2297,7 +2635,7 @@ check_function([{X,_} | XL], R) -> check_function(X, XL, R); check_function([], R) -> R. - + check_function(X0, [{X,_} | XL], R) when X0 /= X -> check_function(X, XL, R); check_function(X0, [{X,_} | _XL], _R) when X0 == X -> @@ -2371,14 +2709,14 @@ term2set(T, Type) -> ?ORDSET(T, Type). fam2digraph(F, G) -> - Fun = fun({From, ToL}) -> + Fun = fun({From, ToL}) -> digraph:add_vertex(G, From), Fun2 = fun(To) -> digraph:add_vertex(G, To), case digraph:add_edge(G, From, To) of - {error, {bad_edge, _}} -> + {error, {bad_edge, _}} -> throw({error, cyclic}); - _ -> + _ -> true end end, @@ -2397,7 +2735,7 @@ digraph_fam([V | Vs], V0, G, L) when V /= V0 -> digraph_fam([], _V0, _G, L) -> reverse(L). -%% -> bool() +%% -> boolean() check_fun(T, F, FunT) -> true = is_type(FunT), {NT, _MaxI} = number_tuples(T, 1), @@ -2424,7 +2762,7 @@ check_for_sort(T, _I) when T =:= ?ANYTYPE -> check_for_sort(T, I) when ?IS_RELATION(T), I =< ?REL_ARITY(T), I >= 1 -> I > 1; check_for_sort(_T, _I) -> - error. + error. inverse_substitution(L, Fun, Sort) -> %% One easily sees that the inverse of the tuples created by @@ -2477,11 +2815,11 @@ match_types(Type1, Type2) -> match_types1(Type1, Type2). match_types1(Atom, Atom) when ?IS_ATOM_TYPE(Atom) -> true; -match_types1(?ANYTYPE, _) -> +match_types1(?ANYTYPE, _) -> true; -match_types1(_, ?ANYTYPE) -> +match_types1(_, ?ANYTYPE) -> true; -match_types1(?SET_OF(Type1), ?SET_OF(Type2)) -> +match_types1(?SET_OF(Type1), ?SET_OF(Type2)) -> match_types1(Type1, Type2); match_types1(T1, T2) when tuple_size(T1) =:= tuple_size(T2) -> match_typesl(tuple_size(T1), T1, T2); diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl index 264348180f..30eac4f07d 100644 --- a/lib/stdlib/src/string.erl +++ b/lib/stdlib/src/string.erl @@ -29,23 +29,23 @@ %%--------------------------------------------------------------------------- --type direction() :: 'left' | 'right' | 'both'. - -%%--------------------------------------------------------------------------- - %% Robert's bit %% len(String) %% Return the length of a string. --spec len(string()) -> non_neg_integer(). +-spec len(String) -> Length when + String :: string(), + Length :: non_neg_integer(). len(S) -> length(S). %% equal(String1, String2) %% Test if 2 strings are equal. --spec equal(string(), string()) -> boolean(). +-spec equal(String1, String2) -> boolean() when + String1 :: string(), + String2 :: string(). equal(S, S) -> true; equal(_, _) -> false. @@ -53,7 +53,10 @@ equal(_, _) -> false. %% concat(String1, String2) %% Concatenate 2 strings. --spec concat(string(), string()) -> string(). +-spec concat(String1, String2) -> String3 when + String1 :: string(), + String2 :: string(), + String3 :: string(). concat(S1, S2) -> S1 ++ S2. @@ -61,7 +64,10 @@ concat(S1, S2) -> S1 ++ S2. %% rchr(String, Char) %% Return the first/last index of the character in a string. --spec chr(string(), char()) -> non_neg_integer(). +-spec chr(String, Character) -> Index when + String :: string(), + Character :: char(), + Index :: non_neg_integer(). chr(S, C) when is_integer(C) -> chr(S, C, 1). @@ -69,7 +75,10 @@ chr([C|_Cs], C, I) -> I; chr([_|Cs], C, I) -> chr(Cs, C, I+1); chr([], _C, _I) -> 0. --spec rchr(string(), char()) -> non_neg_integer(). +-spec rchr(String, Character) -> Index when + String :: string(), + Character :: char(), + Index :: non_neg_integer(). rchr(S, C) when is_integer(C) -> rchr(S, C, 1, 0). @@ -85,7 +94,10 @@ rchr([], _C, _I, L) -> L. %% Return the first/last index of the sub-string in a string. %% index/2 is kept for backwards compatibility. --spec str(string(), string()) -> non_neg_integer(). +-spec str(String, SubString) -> Index when + String :: string(), + SubString :: string(), + Index :: non_neg_integer(). str(S, Sub) when is_list(Sub) -> str(S, Sub, 1). @@ -97,7 +109,10 @@ str([C|S], [C|Sub], I) -> str([_|S], Sub, I) -> str(S, Sub, I+1); str([], _Sub, _I) -> 0. --spec rstr(string(), string()) -> non_neg_integer(). +-spec rstr(String, SubString) -> Index when + String :: string(), + SubString :: string(), + Index :: non_neg_integer(). rstr(S, Sub) when is_list(Sub) -> rstr(S, Sub, 1, 0). @@ -116,7 +131,10 @@ prefix(Pre, String) when is_list(Pre), is_list(String) -> false. %% span(String, Chars) -> Length. %% cspan(String, Chars) -> Length. --spec span(string(), string()) -> non_neg_integer(). +-spec span(String, Chars) -> Length when + String :: string(), + Chars :: string(), + Length :: non_neg_integer(). span(S, Cs) when is_list(Cs) -> span(S, Cs, 0). @@ -127,7 +145,10 @@ span([C|S], Cs, I) -> end; span([], _Cs, I) -> I. --spec cspan(string(), string()) -> non_neg_integer(). +-spec cspan(String, Chars) -> Length when + String :: string(), + Chars :: string(), + Length :: non_neg_integer(). cspan(S, Cs) when is_list(Cs) -> cspan(S, Cs, 0). @@ -142,14 +163,21 @@ cspan([], _Cs, I) -> I. %% substr(String, Start, Length) %% Extract a sub-string from String. --spec substr(string(), pos_integer()) -> string(). +-spec substr(String, Start) -> SubString when + String :: string(), + SubString :: string(), + Start :: pos_integer(). substr(String, 1) when is_list(String) -> String; substr(String, S) when is_integer(S), S > 1 -> substr2(String, S). --spec substr(string(), pos_integer(), non_neg_integer()) -> string(). +-spec substr(String, Start, Length) -> SubString when + String :: string(), + SubString :: string(), + Start :: pos_integer(), + Length :: non_neg_integer(). substr(String, S, L) when is_integer(S), S >= 1, is_integer(L), L >= 0 -> substr1(substr2(String, S), L). @@ -163,7 +191,10 @@ substr2([_|String], S) -> substr2(String, S-1). %% tokens(String, Seperators). %% Return a list of tokens seperated by characters in Seperators. --spec tokens(string(), string()) -> [[char(),...]]. +-spec tokens(String, SeparatorList) -> Tokens when + String :: string(), + SeparatorList :: string(), + Tokens :: [Token :: nonempty_string()]. tokens(S, Seps) -> tokens1(S, Seps, []). @@ -184,11 +215,18 @@ tokens2([C|S], Seps, Toks, Cs) -> tokens2([], _Seps, Toks, Cs) -> reverse([reverse(Cs)|Toks]). --spec chars(char(), non_neg_integer()) -> string(). +-spec chars(Character, Number) -> String when + Character :: char(), + Number :: non_neg_integer(), + String :: string(). chars(C, N) -> chars(C, N, []). --spec chars(char(), non_neg_integer(), string()) -> string(). +-spec chars(Character, Number, Tail) -> String when + Character :: char(), + Number :: non_neg_integer(), + Tail :: string(), + String :: string(). chars(C, N, Tail) when N > 0 -> chars(C, N-1, [C|Tail]); @@ -199,7 +237,10 @@ chars(C, 0, Tail) when is_integer(C) -> %%% COPIES %%% --spec copies(string(), non_neg_integer()) -> string(). +-spec copies(String, Number) -> Copies when + String :: string(), + Copies :: string(), + Number :: non_neg_integer(). copies(CharList, Num) when is_list(CharList), is_integer(Num), Num >= 0 -> copies(CharList, Num, []). @@ -211,11 +252,16 @@ copies(CharList, Num, R) -> %%% WORDS %%% --spec words(string()) -> pos_integer(). +-spec words(String) -> Count when + String :: string(), + Count :: pos_integer(). words(String) -> words(String, $\s). --spec words(string(), char()) -> pos_integer(). +-spec words(String, Character) -> Count when + String :: string(), + Character :: char(), + Count :: pos_integer(). words(String, Char) when is_integer(Char) -> w_count(strip(String, both, Char), Char, 0). @@ -226,11 +272,18 @@ w_count([_H|T], Char, Num) -> w_count(T, Char, Num). %%% SUB_WORDS %%% --spec sub_word(string(), integer()) -> string(). +-spec sub_word(String, Number) -> Word when + String :: string(), + Word :: string(), + Number :: integer(). sub_word(String, Index) -> sub_word(String, Index, $\s). --spec sub_word(string(), integer(), char()) -> string(). +-spec sub_word(String, Number, Character) -> Word when + String :: string(), + Word :: string(), + Number :: integer(), + Character :: char(). sub_word(String, Index, Char) when is_integer(Index), is_integer(Char) -> case words(String, Char) of @@ -254,14 +307,21 @@ s_word([_|T],Stop,Char,Index,Res) when Index < Stop -> strip(String) -> strip(String, both). --spec strip(string(), direction()) -> string(). +-spec strip(String, Direction) -> Stripped when + String :: string(), + Stripped :: string(), + Direction :: left | right | both. strip(String, left) -> strip_left(String, $\s); strip(String, right) -> strip_right(String, $\s); strip(String, both) -> strip_right(strip_left(String, $\s), $\s). --spec strip(string(), direction(), char()) -> string(). +-spec strip(String, Direction, Character) -> Stripped when + String :: string(), + Stripped :: string(), + Direction :: left | right | both, + Character :: char(). strip(String, right, Char) -> strip_right(String, Char); strip(String, left, Char) -> strip_left(String, Char); @@ -285,11 +345,18 @@ strip_right([], Sc) when is_integer(Sc) -> %%% LEFT %%% --spec left(string(), non_neg_integer()) -> string(). +-spec left(String, Number) -> Left when + String :: string(), + Left :: string(), + Number :: non_neg_integer(). left(String, Len) when is_integer(Len) -> left(String, Len, $\s). --spec left(string(), non_neg_integer(), char()) -> string(). +-spec left(String, Number, Character) -> Left when + String :: string(), + Left :: string(), + Number :: non_neg_integer(), + Character :: char(). left(String, Len, Char) when is_integer(Char) -> Slen = length(String), @@ -303,11 +370,18 @@ l_pad(String, Num, Char) -> String ++ chars(Char, Num). %%% RIGHT %%% --spec right(string(), non_neg_integer()) -> string(). +-spec right(String, Number) -> Right when + String :: string(), + Right :: string(), + Number :: non_neg_integer(). right(String, Len) when is_integer(Len) -> right(String, Len, $\s). --spec right(string(), non_neg_integer(), char()) -> string(). +-spec right(String, Number, Character) -> Right when + String :: string(), + Right :: string(), + Number :: non_neg_integer(), + Character :: char(). right(String, Len, Char) when is_integer(Char) -> Slen = length(String), @@ -321,11 +395,18 @@ r_pad(String, Num, Char) -> chars(Char, Num, String). %%% CENTRE %%% --spec centre(string(), non_neg_integer()) -> string(). +-spec centre(String, Number) -> Centered when + String :: string(), + Centered :: string(), + Number :: non_neg_integer(). centre(String, Len) when is_integer(Len) -> centre(String, Len, $\s). --spec centre(string(), non_neg_integer(), char()) -> string(). +-spec centre(String, Number, Character) -> Centered when + String :: string(), + Centered :: string(), + Number :: non_neg_integer(), + Character :: char(). centre(String, 0, Char) when is_list(String), is_integer(Char) -> []; % Strange cases to centre string @@ -341,11 +422,18 @@ centre(String, Len, Char) when is_integer(Char) -> %%% SUB_STRING %%% --spec sub_string(string(), pos_integer()) -> string(). +-spec sub_string(String, Start) -> SubString when + String :: string(), + SubString :: string(), + Start :: pos_integer(). sub_string(String, Start) -> substr(String, Start). --spec sub_string(string(), pos_integer(), pos_integer()) -> string(). +-spec sub_string(String, Start, Stop) -> SubString when + String :: string(), + SubString :: string(), + Start :: pos_integer(), + Stop :: pos_integer(). sub_string(String, Start, Stop) -> substr(String, Start, Stop - Start + 1). @@ -370,23 +458,34 @@ to_upper_char(C) when is_integer(C), 16#F8 =< C, C =< 16#FE -> to_upper_char(C) -> C. --spec to_lower(string()) -> string() - ; (char()) -> char(). +-spec to_lower(String) -> Result when + String :: string(), + Result :: string() + ; (Char) -> CharResult when + Char :: char(), + CharResult :: char(). to_lower(S) when is_list(S) -> [to_lower_char(C) || C <- S]; to_lower(C) when is_integer(C) -> to_lower_char(C). --spec to_upper(string()) -> string() - ; (char()) -> char(). +-spec to_upper(String) -> Result when + String :: string(), + Result :: string() + ; (Char) -> CharResult when + Char :: char(), + CharResult :: char(). to_upper(S) when is_list(S) -> [to_upper_char(C) || C <- S]; to_upper(C) when is_integer(C) -> to_upper_char(C). --spec join([string()], string()) -> string(). +-spec join(StringList, Separator) -> String when + StringList :: [string()], + Separator :: string(), + String :: string(). join([], Sep) when is_list(Sep) -> []; diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 3c5800effa..9da0d52f8c 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -27,27 +27,34 @@ which_children/1, count_children/1, check_childspecs/1]). --export([behaviour_info/1]). - %% Internal exports -export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]). -export([handle_cast/2]). %%-------------------------------------------------------------------------- --export_type([child_spec/0, del_err/0, startchild_ret/0, strategy/0]). +-export_type([child_spec/0, startchild_ret/0, strategy/0]). %%-------------------------------------------------------------------------- --type child_id() :: pid() | 'undefined'. --type mfargs() :: {module(), atom(), [term()] | undefined}. +-type child() :: pid() | 'undefined'. +-type child_id() :: term(). +-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}. -type modules() :: [module()] | 'dynamic'. -type restart() :: 'permanent' | 'transient' | 'temporary'. -type shutdown() :: 'brutal_kill' | timeout(). -type worker() :: 'worker' | 'supervisor'. --type sup_name() :: {'local', atom()} | {'global', atom()}. --type sup_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid(). --type child_spec() :: {term(),mfargs(),restart(),shutdown(),worker(),modules()}. +-type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}. +-type sup_ref() :: (Name :: atom()) + | {Name :: atom(), Node :: node()} + | {'global', Name :: atom()} + | pid(). +-type child_spec() :: {Id :: child_id(), + StartFunc :: mfargs(), + Restart :: restart(), + Shutdown :: shutdown(), + Type :: worker(), + Modules :: modules()}. -type strategy() :: 'one_for_all' | 'one_for_one' | 'rest_for_one' | 'simple_one_for_one'. @@ -55,21 +62,23 @@ %%-------------------------------------------------------------------------- -record(child, {% pid is undefined when child is not running - pid = undefined :: child_id(), + pid = undefined :: child(), name, mfargs :: mfargs(), restart_type :: restart(), shutdown :: shutdown(), child_type :: worker(), modules = [] :: modules()}). --type child() :: #child{}. +-type child_rec() :: #child{}. -define(DICT, dict). +-define(SETS, sets). +-define(SET, set). -record(state, {name, strategy :: strategy(), - children = [] :: [child()], - dynamics :: ?DICT() | list(), + children = [] :: [child_rec()], + dynamics :: ?DICT() | ?SET(), intensity :: non_neg_integer(), period :: pos_integer(), restarts = [], @@ -79,14 +88,12 @@ -define(is_simple(State), State#state.strategy =:= simple_one_for_one). -%%-------------------------------------------------------------------------- - --spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}]. - -behaviour_info(callbacks) -> - [{init,1}]; -behaviour_info(_Other) -> - undefined. +-callback init(Args :: term()) -> + {ok, {{RestartStrategy :: strategy(), + MaxR :: non_neg_integer(), + MaxT :: non_neg_integer()}, + [ChildSpec :: child_spec()]}} + | ignore. %%% --------------------------------------------------- %%% This is a general process supervisor built upon gen_server.erl. @@ -97,11 +104,16 @@ behaviour_info(_Other) -> -type startlink_err() :: {'already_started', pid()} | 'shutdown' | term(). -type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}. --spec start_link(module(), term()) -> startlink_ret(). +-spec start_link(Module, Args) -> startlink_ret() when + Module :: module(), + Args :: term(). start_link(Mod, Args) -> gen_server:start_link(supervisor, {self, Mod, Args}, []). --spec start_link(sup_name(), module(), term()) -> startlink_ret(). +-spec start_link(SupName, Module, Args) -> startlink_ret() when + SupName :: sup_name(), + Module :: module(), + Args :: term(). start_link(SupName, Mod, Args) -> gen_server:start_link(SupName, supervisor, {SupName, Mod, Args}, []). @@ -109,24 +121,33 @@ start_link(SupName, Mod, Args) -> %%% Interface functions. %%% --------------------------------------------------- --type info() :: term(). -type startchild_err() :: 'already_present' - | {'already_started', child_id()} | term(). --type startchild_ret() :: {'ok', child_id()} | {'ok', child_id(), info()} + | {'already_started', Child :: child()} | term(). +-type startchild_ret() :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} | {'error', startchild_err()}. --spec start_child(sup_ref(), child_spec() | [term()]) -> startchild_ret(). +-spec start_child(SupRef, ChildSpec) -> startchild_ret() when + SupRef :: sup_ref(), + ChildSpec :: child_spec() | (List :: [term()]). start_child(Supervisor, ChildSpec) -> call(Supervisor, {start_child, ChildSpec}). --type restart_err() :: 'running' | 'not_found' | 'simple_one_for_one' | term(). --spec restart_child(sup_ref(), term()) -> - {'ok', child_id()} | {'ok', child_id(), info()} | {'error', restart_err()}. +-spec restart_child(SupRef, Id) -> Result when + SupRef :: sup_ref(), + Id :: child_id(), + Result :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} + | {'error', Error}, + Error :: 'running' | 'not_found' | 'simple_one_for_one' | term(). restart_child(Supervisor, Name) -> call(Supervisor, {restart_child, Name}). --type del_err() :: 'running' | 'not_found' | 'simple_one_for_one'. --spec delete_child(sup_ref(), term()) -> 'ok' | {'error', del_err()}. +-spec delete_child(SupRef, Id) -> Result when + SupRef :: sup_ref(), + Id :: child_id(), + Result :: 'ok' | {'error', Error}, + Error :: 'running' | 'not_found' | 'simple_one_for_one'. delete_child(Supervisor, Name) -> call(Supervisor, {delete_child, Name}). @@ -137,22 +158,39 @@ delete_child(Supervisor, Name) -> %% way (maybe killed). %%----------------------------------------------------------------- --type term_err() :: 'not_found' | 'simple_one_for_one'. --spec terminate_child(sup_ref(), term()) -> 'ok' | {'error', term_err()}. +-spec terminate_child(SupRef, Id) -> Result when + SupRef :: sup_ref(), + Id :: pid() | child_id(), + Result :: 'ok' | {'error', Error}, + Error :: 'not_found' | 'simple_one_for_one'. terminate_child(Supervisor, Name) -> call(Supervisor, {terminate_child, Name}). --spec which_children(sup_ref()) -> [{term(), child_id(), worker(), modules()}]. +-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when + SupRef :: sup_ref(), + Id :: child_id() | undefined, + Child :: child(), + Type :: worker(), + Modules :: modules(). which_children(Supervisor) -> call(Supervisor, which_children). +-spec count_children(SupRef) -> PropListOfCounts when + SupRef :: sup_ref(), + PropListOfCounts :: [Count], + Count :: {specs, ChildSpecCount :: non_neg_integer()} + | {active, ActiveProcessCount :: non_neg_integer()} + | {supervisors, ChildSupervisorCount :: non_neg_integer()} + |{workers, ChildWorkerCount :: non_neg_integer()}. count_children(Supervisor) -> call(Supervisor, count_children). call(Supervisor, Req) -> gen_server:call(Supervisor, Req, infinity). --spec check_childspecs([child_spec()]) -> 'ok' | {'error', term()}. +-spec check_childspecs(ChildSpecs) -> Result when + ChildSpecs :: [child_spec()], + Result :: 'ok' | {'error', Error :: term()}. check_childspecs(ChildSpecs) when is_list(ChildSpecs) -> case check_startspec(ChildSpecs) of {ok, _} -> ok; @@ -220,12 +258,12 @@ init_dynamic(_State, StartSpec) -> %%----------------------------------------------------------------- %% Func: start_children/2 -%% Args: Children = [child()] in start order +%% Args: Children = [child_rec()] in start order %% SupName = {local, atom()} | {global, atom()} | {pid(), Mod} %% Purpose: Start all children. The new list contains #child's %% with pids. %% Returns: {ok, NChildren} | {error, NChildren} -%% NChildren = [child()] in termination order (reversed +%% NChildren = [child_rec()] in termination order (reversed %% start order) %%----------------------------------------------------------------- start_children(Children, SupName) -> start_children(Children, [], SupName). @@ -297,8 +335,26 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) -> {reply, What, State} end; -%%% The requests terminate_child, delete_child and restart_child are -%%% invalid for simple_one_for_one supervisors. +%% terminate_child for simple_one_for_one can only be done with pid +handle_call({terminate_child, Name}, _From, State) when not is_pid(Name), + ?is_simple(State) -> + {reply, {error, simple_one_for_one}, State}; + +handle_call({terminate_child, Name}, _From, State) -> + case get_child(Name, State, ?is_simple(State)) of + {value, Child} -> + case do_terminate(Child, State#state.name) of + #child{restart_type=RT} when RT=:=temporary; ?is_simple(State) -> + {reply, ok, state_del_child(Child, State)}; + NChild -> + {reply, ok, replace_child(NChild, State)} + end; + false -> + {reply, {error, not_found}, State} + end; + +%%% The requests delete_child and restart_child are invalid for +%%% simple_one_for_one supervisors. handle_call({_Req, _Data}, _From, State) when ?is_simple(State) -> {reply, {error, simple_one_for_one}, State}; @@ -341,21 +397,12 @@ handle_call({delete_child, Name}, _From, State) -> {reply, {error, not_found}, State} end; -handle_call({terminate_child, Name}, _From, State) -> - case get_child(Name, State) of - {value, Child} -> - NChild = do_terminate(Child, State#state.name), - {reply, ok, replace_child(NChild, State)}; - _ -> - {reply, {error, not_found}, State} - end; - handle_call(which_children, _From, #state{children = [#child{restart_type = temporary, child_type = CT, modules = Mods}]} = State) when ?is_simple(State) -> - Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end, dynamics_db(temporary, - State#state.dynamics)), + Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end, + ?SETS:to_list(dynamics_db(temporary, State#state.dynamics))), {reply, Reply, State}; handle_call(which_children, _From, #state{children = [#child{restart_type = RType, @@ -380,7 +427,7 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = temp child_type = CT}]} = State) when ?is_simple(State) -> {Active, Count} = - lists:foldl(fun(Pid, {Alive, Tot}) -> + ?SETS:fold(fun(Pid, {Alive, Tot}) -> if is_pid(Pid) -> {Alive+1, Tot +1}; true -> {Alive, Tot + 1} end end, {0, 0}, dynamics_db(temporary, State#state.dynamics)), @@ -610,6 +657,9 @@ do_restart(_, normal, Child, State) -> do_restart(_, shutdown, Child, State) -> NState = state_del_child(Child, State), {ok, NState}; +do_restart(_, {shutdown, _Term}, Child, State) -> + NState = state_del_child(Child, State), + {ok, NState}; do_restart(transient, Reason, Child, State) -> report_error(child_terminated, Reason, Child, State#state.name), restart(Child, State); @@ -676,14 +726,21 @@ restart(one_for_all, Child, State) -> %%----------------------------------------------------------------- %% Func: terminate_children/2 -%% Args: Children = [child()] in termination order +%% Args: Children = [child_rec()] in termination order %% SupName = {local, atom()} | {global, atom()} | {pid(),Mod} -%% Returns: NChildren = [child()] in +%% Returns: NChildren = [child_rec()] in %% startup order (reversed termination order) %%----------------------------------------------------------------- terminate_children(Children, SupName) -> terminate_children(Children, SupName, []). +%% Temporary children should not be restarted and thus should +%% be skipped when building the list of terminated children, although +%% we do want them to be shut down as many functions from this module +%% use this function to just clear everything. +terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) -> + do_terminate(Child, SupName), + terminate_children(Children, SupName, Res); terminate_children([Child | Children], SupName, Res) -> NChild = do_terminate(Child, SupName), terminate_children(Children, SupName, [NChild | Res]); @@ -791,24 +848,27 @@ save_child(Child, #state{children = Children} = State) -> State#state{children = [Child |Children]}. save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = [Pid | dynamics_db(temporary, Dynamics)]}; + State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))}; save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) -> State#state{dynamics = ?DICT:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. dynamics_db(temporary, undefined) -> - []; + ?SETS:new(); dynamics_db(_, undefined) -> ?DICT:new(); dynamics_db(_,Dynamics) -> Dynamics. -dynamic_child_args(_, Dynamics) when is_list(Dynamics)-> - {ok, undefined}; dynamic_child_args(Pid, Dynamics) -> - ?DICT:find(Pid, Dynamics). + case ?SETS:is_set(Dynamics) of + true -> + {ok, undefined}; + false -> + ?DICT:find(Pid, Dynamics) + end. state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) -> - NDynamics = lists:delete(Pid, dynamics_db(temporary, State#state.dynamics)), + NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)), State#state{dynamics = NDynamics}; state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) -> NDynamics = ?DICT:erase(Pid, dynamics_db(RType, State#state.dynamics)), @@ -817,8 +877,12 @@ state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), State#state{children = NChildren}. +del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary -> + Chs; del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name -> [Ch#child{pid = undefined} | Chs]; +del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary -> + Chs; del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid -> [Ch#child{pid = undefined} | Chs]; del_child(Name, [Ch|Chs]) -> @@ -841,7 +905,31 @@ split_child(_, [], After) -> {lists:reverse(After), []}. get_child(Name, State) -> + get_child(Name, State, false). +get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) -> + get_dynamic_child(Pid, State); +get_child(Name, State, _) -> lists:keysearch(Name, #child.name, State#state.children). + +get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> + case is_dynamic_pid(Pid, dynamics_db(Child#child.restart_type, Dynamics)) of + true -> + {value, Child#child{pid=Pid}}; + false -> + case erlang:is_process_alive(Pid) of + true -> false; + false -> {value, Child} + end + end. + +is_dynamic_pid(Pid, Dynamics) -> + case ?SETS:is_set(Dynamics) of + true -> + ?SETS:is_element(Pid, Dynamics); + false -> + ?DICT:is_key(Pid, Dynamics) + end. + replace_child(Child, State) -> Chs = do_replace_child(Child, State#state.children), State#state{children = Chs}. @@ -916,7 +1004,7 @@ supname(N, _) -> N. %%% Shutdown = integer() | infinity | brutal_kill %%% ChildType = supervisor | worker %%% Modules = [atom()] | dynamic -%%% Returns: {ok, [child()]} | Error +%%% Returns: {ok, [child_rec()]} | Error %%% ------------------------------------------------------ check_startspec(Children) -> check_startspec(Children, []). diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl index 3d2bd2c9a5..e8405ab9a4 100644 --- a/lib/stdlib/src/supervisor_bridge.erl +++ b/lib/stdlib/src/supervisor_bridge.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -22,15 +22,14 @@ %% External exports -export([start_link/2, start_link/3]). --export([behaviour_info/1]). %% Internal exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). -export([code_change/3]). -behaviour_info(callbacks) -> - [{init,1},{terminate,2}]; -behaviour_info(_Other) -> - undefined. +-callback init(Args :: term()) -> + {ok, Pid :: pid(), State :: term()} | ignore | {error, Error :: term()}. +-callback terminate(Reason :: (shutdown | term()), State :: term()) -> + Ignored :: term(). %%%----------------------------------------------------------------- %%% This is a rewrite of supervisor_bridge from BS.3. @@ -49,9 +48,25 @@ behaviour_info(_Other) -> %%%----------------------------------------------------------------- -record(state, {mod, pid, child_state, name}). +-spec start_link(Module, Args) -> Result when + Module :: module(), + Args :: term(), + Result :: {ok, Pid} | ignore | {error, Error}, + Error :: {already_started, Pid} | term(), + Pid :: pid(). + start_link(Mod, StartArgs) -> gen_server:start_link(supervisor_bridge, [Mod, StartArgs, self], []). +-spec start_link(SupBridgeName, Module, Args) -> Result when + SupBridgeName :: {local, Name} | {global, Name}, + Name :: atom(), + Module :: module(), + Args :: term(), + Result :: {ok, Pid} | ignore | {error, Error}, + Error :: {already_started, Pid} | term(), + Pid :: pid(). + start_link(Name, Mod, StartArgs) -> gen_server:start_link(Name, supervisor_bridge, [Mod, StartArgs, Name], []). diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl index 12209c16d7..f34201604c 100644 --- a/lib/stdlib/src/sys.erl +++ b/lib/stdlib/src/sys.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -33,22 +33,74 @@ %%----------------------------------------------------------------- -type name() :: pid() | atom() | {'global', atom()}. --type system_event() :: {'in', _Msg} | {'in', _Msg, _From} | {'out', _Msg, _To}. +-type system_event() :: {'in', Msg :: _} + | {'in', Msg :: _, From :: _} + | {'out', Msg :: _, To :: _} + | term(). +-opaque dbg_opt() :: list(). +-type dbg_fun() :: fun((FuncState :: _, + Event :: system_event(), + ProcState :: _) -> 'done' | (NewFuncState :: _)). %%----------------------------------------------------------------- %% System messages %%----------------------------------------------------------------- +-spec suspend(Name) -> Void when + Name :: name(), + Void :: term(). suspend(Name) -> send_system_msg(Name, suspend). +-spec suspend(Name, Timeout) -> Void when + Name :: name(), + Timeout :: timeout(), + Void :: term(). suspend(Name, Timeout) -> send_system_msg(Name, suspend, Timeout). +-spec resume(Name) -> Void when + Name :: name(), + Void :: term(). resume(Name) -> send_system_msg(Name, resume). +-spec resume(Name, Timeout) -> Void when + Name :: name(), + Timeout :: timeout(), + Void :: term(). resume(Name, Timeout) -> send_system_msg(Name, resume, Timeout). +-spec get_status(Name) -> Status when + Name :: name(), + Status :: {status, Pid :: pid(), {module, Module :: module()}, [SItem]}, + SItem :: (PDict :: [{Key :: term(), Value :: term()}]) + | (SysState :: 'running' | 'suspended') + | (Parent :: pid()) + | (Dbg :: dbg_opt()) + | (Misc :: term()). get_status(Name) -> send_system_msg(Name, get_status). +-spec get_status(Name, Timeout) -> Status when + Name :: name(), + Timeout :: timeout(), + Status :: {status, Pid :: pid(), {module, Module :: module()}, [SItem]}, + SItem :: (PDict :: [{Key :: term(), Value :: term()}]) + | (SysState :: 'running' | 'suspended') + | (Parent :: pid()) + | (Dbg :: dbg_opt()) + | (Misc :: term()). get_status(Name, Timeout) -> send_system_msg(Name, get_status, Timeout). +-spec change_code(Name, Module, OldVsn, Extra) -> 'ok' | {error, Reason} when + Name :: name(), + Module :: module(), + OldVsn :: 'undefined' | term(), + Extra :: term(), + Reason :: term(). change_code(Name, Mod, Vsn, Extra) -> send_system_msg(Name, {change_code, Mod, Vsn, Extra}). +-spec change_code(Name, Module, OldVsn, Extra, Timeout) -> + 'ok' | {error, Reason} when + Name :: name(), + Module :: module(), + OldVsn :: 'undefined' | term(), + Extra :: term(), + Timeout :: timeout(), + Reason :: term(). change_code(Name, Mod, Vsn, Extra, Timeout) -> send_system_msg(Name, {change_code, Mod, Vsn, Extra}, Timeout). @@ -56,52 +108,116 @@ change_code(Name, Mod, Vsn, Extra, Timeout) -> %% Debug commands %%----------------------------------------------------------------- --type log_flag() :: 'true' | {'true',pos_integer()} | 'false' | 'get' | 'print'. - --spec log(name(), log_flag()) -> 'ok' | {'ok', [system_event()]}. +-spec log(Name, Flag) -> 'ok' | {'ok', [system_event()]} when + Name :: name(), + Flag :: 'true' | + {'true', N :: pos_integer()} + | 'false' | 'get' | 'print'. log(Name, Flag) -> send_system_msg(Name, {debug, {log, Flag}}). --spec log(name(), log_flag(), timeout()) -> 'ok' | {'ok', [system_event()]}. +-spec log(Name, Flag, Timeout) -> 'ok' | {'ok', [system_event()]} when + Name :: name(), + Flag :: 'true' | + {'true', N :: pos_integer()} + | 'false' | 'get' | 'print', + Timeout :: timeout(). log(Name, Flag, Timeout) -> send_system_msg(Name, {debug, {log, Flag}}, Timeout). --spec trace(name(), boolean()) -> 'ok'. +-spec trace(Name, Flag) -> 'ok' when + Name :: name(), + Flag :: boolean(). trace(Name, Flag) -> send_system_msg(Name, {debug, {trace, Flag}}). --spec trace(name(), boolean(), timeout()) -> 'ok'. +-spec trace(Name, Flag, Timeout) -> 'ok' when + Name :: name(), + Flag :: boolean(), + Timeout :: timeout(). trace(Name, Flag, Timeout) -> send_system_msg(Name, {debug, {trace, Flag}}, Timeout). --type l2f_fname() :: string() | 'false'. - --spec log_to_file(name(), l2f_fname()) -> 'ok' | {'error','open_file'}. +-spec log_to_file(Name, Flag) -> 'ok' | {'error','open_file'} when + Name :: name(), + Flag :: (FileName :: string()) | 'false'. log_to_file(Name, FileName) -> send_system_msg(Name, {debug, {log_to_file, FileName}}). --spec log_to_file(name(), l2f_fname(), timeout()) -> 'ok' | {'error','open_file'}. +-spec log_to_file(Name, Flag, Timeout) -> 'ok' | {'error','open_file'} when + Name :: name(), + Flag :: (FileName :: string()) | 'false', + Timeout :: timeout(). log_to_file(Name, FileName, Timeout) -> send_system_msg(Name, {debug, {log_to_file, FileName}}, Timeout). +-spec statistics(Name, Flag) -> 'ok' | {'ok', Statistics} when + Name :: name(), + Flag :: 'true' | 'false' | 'get', + Statistics :: [StatisticsTuple] | no_statistics, + StatisticsTuple :: {'start_time', DateTime1} + | {'current_time', DateTime2} + | {'reductions', non_neg_integer()} + | {'messages_in', non_neg_integer()} + | {'messages_out', non_neg_integer()}, + DateTime1 :: file:date_time(), + DateTime2 :: file:date_time(). statistics(Name, Flag) -> send_system_msg(Name, {debug, {statistics, Flag}}). + +-spec statistics(Name, Flag, Timeout) -> 'ok' | {'ok', Statistics} when + Name :: name(), + Flag :: 'true' | 'false' | 'get', + Statistics :: [StatisticsTuple] | no_statistics, + StatisticsTuple :: {'start_time', DateTime1} + | {'current_time', DateTime2} + | {'reductions', non_neg_integer()} + | {'messages_in', non_neg_integer()} + | {'messages_out', non_neg_integer()}, + DateTime1 :: file:date_time(), + DateTime2 :: file:date_time(), + Timeout :: timeout(). statistics(Name, Flag, Timeout) -> send_system_msg(Name, {debug, {statistics, Flag}}, Timeout). --spec no_debug(name()) -> 'ok'. +-spec no_debug(Name) -> 'ok' when + Name :: name(). no_debug(Name) -> send_system_msg(Name, {debug, no_debug}). --spec no_debug(name(), timeout()) -> 'ok'. +-spec no_debug(Name, Timeout) -> 'ok' when + Name :: name(), + Timeout :: timeout(). no_debug(Name, Timeout) -> send_system_msg(Name, {debug, no_debug}, Timeout). +-spec install(Name, FuncSpec) -> Void when + Name :: name(), + FuncSpec :: {Func, FuncState}, + Func :: dbg_fun(), + FuncState :: term(), + Void :: term(). install(Name, {Func, FuncState}) -> send_system_msg(Name, {debug, {install, {Func, FuncState}}}). +-spec install(Name, FuncSpec, Timeout) -> Void when + Name :: name(), + FuncSpec :: {Func, FuncState}, + Func :: dbg_fun(), + FuncState :: term(), + Timeout :: timeout(), + Void :: term(). install(Name, {Func, FuncState}, Timeout) -> send_system_msg(Name, {debug, {install, {Func, FuncState}}}, Timeout). +-spec remove(Name, Func) -> Void when + Name :: name(), + Func :: dbg_fun(), + Void :: term(). remove(Name, Func) -> send_system_msg(Name, {debug, {remove, Func}}). +-spec remove(Name, Func, Timeout) -> Void when + Name :: name(), + Func :: dbg_fun(), + Timeout :: timeout(), + Void :: term(). remove(Name, Func, Timeout) -> send_system_msg(Name, {debug, {remove, Func}}, Timeout). @@ -150,6 +266,14 @@ mfa(Name, Req, Timeout) -> %% The Module must export system_continue/3, system_terminate/4 %% and format_status/2 for status information. %%----------------------------------------------------------------- +-spec handle_system_msg(Msg, From, Parent, Module, Debug, Misc) -> Void when + Msg :: term(), + From :: {pid(), Tag :: _}, + Parent :: pid(), + Module :: module(), + Debug :: [dbg_opt()], + Misc :: term(), + Void :: term(). handle_system_msg(Msg, From, Parent, Module, Debug, Misc) -> handle_system_msg(running, Msg, From, Parent, Module, Debug, Misc, false). @@ -176,6 +300,11 @@ handle_system_msg(SysState, Msg, From, Parent, Mod, Debug, Misc, Hib) -> %% Func is a formatting function, called as Func(Device, Event). %% Returns: [debug_opts()] %%----------------------------------------------------------------- +-spec handle_debug(Debug, FormFunc, Extra, Event) -> [dbg_opt()] when + Debug :: [dbg_opt()], + FormFunc :: dbg_fun(), + Extra :: term(), + Event :: system_event(). handle_debug([{trace, true} | T], FormFunc, State, Event) -> print_event({Event, State, FormFunc}), [{trace, true} | handle_debug(T, FormFunc, State, Event)]; @@ -341,24 +470,36 @@ trim(N, LogData) -> %% Debug structure manipulating functions %%----------------------------------------------------------------- install_debug(Item, Data, Debug) -> - case get_debug(Item, Debug, undefined) of + case get_debug2(Item, Debug, undefined) of undefined -> [{Item, Data} | Debug]; _ -> Debug end. remove_debug(Item, Debug) -> lists:keydelete(Item, 1, Debug). + +-spec get_debug(Item, Debug, Default) -> term() when + Item :: 'log' | 'statistics', + Debug :: [dbg_opt()], + Default :: term(). get_debug(Item, Debug, Default) -> + get_debug2(Item, Debug, Default). + +%% Workaround: accepts more Item types than get_debug/3. +get_debug2(Item, Debug, Default) -> case lists:keysearch(Item, 1, Debug) of {value, {Item, Data}} -> Data; _ -> Default end. +-spec print_log(Debug) -> Void when + Debug :: [dbg_opt()], + Void :: term(). print_log(Debug) -> {_N, Logs} = get_debug(log, Debug, {0, []}), lists:foreach(fun print_event/1, lists:reverse(Logs)). close_log_file(Debug) -> - case get_debug(log_to_file, Debug, []) of + case get_debug2(log_to_file, Debug, []) of [] -> Debug; Fd -> @@ -375,6 +516,15 @@ close_log_file(Debug) -> %% system messages. %% Returns: [debug_opts()] %%----------------------------------------------------------------- + +-spec debug_options(Options) -> [dbg_opt()] when + Options :: [Opt], + Opt :: 'trace' | 'log' | 'statistics' | {'log_to_file', FileName} + | {'install', FuncSpec}, + FileName :: file:name(), + FuncSpec :: {Func, FuncState}, + Func :: dbg_fun(), + FuncState :: term(). debug_options(Options) -> debug_options(Options, []). debug_options([trace | T], Debug) -> diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl index b456c5d6c1..689e42051f 100644 --- a/lib/stdlib/src/timer.erl +++ b/lib/stdlib/src/timer.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -22,7 +22,7 @@ send_after/3, send_after/2, exit_after/3, exit_after/2, kill_after/2, kill_after/1, apply_interval/4, send_interval/3, send_interval/2, - cancel/1, sleep/1, tc/2, tc/3, now_diff/2, + cancel/1, sleep/1, tc/1, tc/2, tc/3, now_diff/2, seconds/1, minutes/1, hours/1, hms/3]). -export([start_link/0, start/0, @@ -46,103 +46,189 @@ %% -opaque tref() :: {integer(), reference()}. -type time() :: non_neg_integer(). --type timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}. %% %% Interface functions %% --spec apply_after(time(), atom(), atom(), [term()]) -> {'ok', tref()} | {'error', term()}. +-spec apply_after(Time, Module, Function, Arguments) -> + {'ok', TRef} | {'error', Reason} when + Time :: time(), + Module :: module(), + Function :: atom(), + Arguments :: [term()], + TRef :: tref(), + Reason :: term(). + apply_after(Time, M, F, A) -> req(apply_after, {Time, {M, F, A}}). --spec send_after(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}. +-spec send_after(Time, Pid, Message) -> {'ok', TRef} | {'error', Reason} when + Time :: time(), + Pid :: pid() | (RegName :: atom()), + Message :: term(), + TRef :: tref(), + Reason :: term(). send_after(Time, Pid, Message) -> req(apply_after, {Time, {?MODULE, send, [Pid, Message]}}). --spec send_after(time(), term()) -> {'ok', tref()} | {'error', term()}. +-spec send_after(Time, Message) -> {'ok', TRef} | {'error', Reason} when + Time :: time(), + Message :: term(), + TRef :: tref(), + Reason :: term(). send_after(Time, Message) -> send_after(Time, self(), Message). --spec exit_after(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}. +-spec exit_after(Time, Pid, Reason1) -> {'ok', TRef} | {'error', Reason2} when + Time :: time(), + Pid :: pid() | (RegName :: atom()), + TRef :: tref(), + Reason1 :: term(), + Reason2 :: term(). exit_after(Time, Pid, Reason) -> req(apply_after, {Time, {erlang, exit, [Pid, Reason]}}). --spec exit_after(time(), term()) -> {'ok', tref()} | {'error', term()}. +-spec exit_after(Time, Reason1) -> {'ok', TRef} | {'error', Reason2} when + Time :: time(), + TRef :: tref(), + Reason1 :: term(), + Reason2 :: term(). exit_after(Time, Reason) -> exit_after(Time, self(), Reason). --spec kill_after(time(), pid() | atom()) -> {'ok', tref()} | {'error', term()}. +-spec kill_after(Time, Pid) -> {'ok', TRef} | {'error', Reason2} when + Time :: time(), + Pid :: pid() | (RegName :: atom()), + TRef :: tref(), + Reason2 :: term(). kill_after(Time, Pid) -> exit_after(Time, Pid, kill). --spec kill_after(time()) -> {'ok', tref()} | {'error', term()}. +-spec kill_after(Time) -> {'ok', TRef} | {'error', Reason2} when + Time :: time(), + TRef :: tref(), + Reason2 :: term(). kill_after(Time) -> exit_after(Time, self(), kill). --spec apply_interval(time(), atom(), atom(), [term()]) -> {'ok', tref()} | {'error', term()}. +-spec apply_interval(Time, Module, Function, Arguments) -> + {'ok', TRef} | {'error', Reason} when + Time :: time(), + Module :: module(), + Function :: atom(), + Arguments :: [term()], + TRef :: tref(), + Reason :: term(). apply_interval(Time, M, F, A) -> req(apply_interval, {Time, self(), {M, F, A}}). --spec send_interval(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}. +-spec send_interval(Time, Pid, Message) -> + {'ok', TRef} | {'error', Reason} when + Time :: time(), + Pid :: pid() | (RegName :: atom()), + Message :: term(), + TRef :: tref(), + Reason :: term(). send_interval(Time, Pid, Message) -> req(apply_interval, {Time, Pid, {?MODULE, send, [Pid, Message]}}). --spec send_interval(time(), term()) -> {'ok', tref()} | {'error', term()}. +-spec send_interval(Time, Message) -> {'ok', TRef} | {'error', Reason} when + Time :: time(), + Message :: term(), + TRef :: tref(), + Reason :: term(). send_interval(Time, Message) -> send_interval(Time, self(), Message). --spec cancel(tref()) -> {'ok', 'cancel'} | {'error', term()}. +-spec cancel(TRef) -> {'ok', 'cancel'} | {'error', Reason} when + TRef :: tref(), + Reason :: term(). cancel(BRef) -> req(cancel, BRef). --spec sleep(timeout()) -> 'ok'. +-spec sleep(Time) -> 'ok' when + Time :: timeout(). sleep(T) -> receive after T -> ok end. +%% +%% Measure the execution time (in microseconds) for Fun(). +%% +-spec tc(Fun) -> {Time, Value} when + Fun :: function(), + Time :: integer(), + Value :: term(). +tc(F) -> + Before = os:timestamp(), + Val = F(), + After = os:timestamp(), + {now_diff(After, Before), Val}. %% %% Measure the execution time (in microseconds) for Fun(Args). %% --spec tc(function(), [_]) -> {time(), term()}. +-spec tc(Fun, Arguments) -> {Time, Value} when + Fun :: function(), + Arguments :: [term()], + Time :: integer(), + Value :: term(). tc(F, A) -> - Before = erlang:now(), - Val = (catch apply(F, A)), - After = erlang:now(), + Before = os:timestamp(), + Val = apply(F, A), + After = os:timestamp(), {now_diff(After, Before), Val}. %% %% Measure the execution time (in microseconds) for an MFA. %% --spec tc(atom(), atom(), [term()]) -> {time(), term()}. +-spec tc(Module, Function, Arguments) -> {Time, Value} when + Module :: module(), + Function :: atom(), + Arguments :: [term()], + Time :: integer(), + Value :: term(). tc(M, F, A) -> - Before = erlang:now(), - Val = (catch apply(M, F, A)), - After = erlang:now(), + Before = os:timestamp(), + Val = apply(M, F, A), + After = os:timestamp(), {now_diff(After, Before), Val}. %% %% Calculate the time difference (in microseconds) of two %% erlang:now() timestamps, T2-T1. %% --spec now_diff(timestamp(), timestamp()) -> integer(). +-spec now_diff(T2, T1) -> Tdiff when + T1 :: erlang:timestamp(), + T2 :: erlang:timestamp(), + Tdiff :: integer(). now_diff({A2, B2, C2}, {A1, B1, C1}) -> ((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1. %% %% Convert seconds, minutes etc. to milliseconds. %% --spec seconds(non_neg_integer()) -> non_neg_integer(). +-spec seconds(Seconds) -> MilliSeconds when + Seconds :: non_neg_integer(), + MilliSeconds :: non_neg_integer(). seconds(Seconds) -> 1000*Seconds. --spec minutes(non_neg_integer()) -> non_neg_integer(). +-spec minutes(Minutes) -> MilliSeconds when + Minutes :: non_neg_integer(), + MilliSeconds :: non_neg_integer(). minutes(Minutes) -> 1000*60*Minutes. --spec hours(non_neg_integer()) -> non_neg_integer(). +-spec hours(Hours) -> MilliSeconds when + Hours :: non_neg_integer(), + MilliSeconds :: non_neg_integer(). hours(Hours) -> 1000*60*60*Hours. --spec hms(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> non_neg_integer(). +-spec hms(Hours, Minutes, Seconds) -> MilliSeconds when + Hours :: non_neg_integer(), + Minutes :: non_neg_integer(), + Seconds :: non_neg_integer(), + MilliSeconds :: non_neg_integer(). hms(H, M, S) -> hours(H) + minutes(M) + seconds(S). diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl index 12bc60623d..e9b90befe6 100644 --- a/lib/stdlib/src/unicode.erl +++ b/lib/stdlib/src/unicode.erl @@ -30,12 +30,34 @@ characters_to_binary/3, bom_to_encoding/1, encoding_to_bom/1]). --export_type([encoding/0]). +-export_type([chardata/0, charlist/0, encoding/0, external_chardata/0, + external_charlist/0, latin1_chardata/0, + latin1_charlist/0, unicode_binary/0, unicode_char/0]). -type encoding() :: 'latin1' | 'unicode' | 'utf8' | 'utf16' | {'utf16', endian()} | 'utf32' | {'utf32', endian()}. -type endian() :: 'big' | 'little'. +-type unicode_binary() :: binary(). +-type unicode_char() :: non_neg_integer(). +-type charlist() :: [unicode_char() | unicode_binary() | charlist()]. +-type chardata() :: charlist() | unicode_binary(). +-type external_unicode_binary() :: binary(). +-type external_chardata() :: external_charlist() | external_unicode_binary(). +-type external_charlist() :: [unicode_char() | external_unicode_binary() + | external_charlist()]. +-type latin1_binary() :: binary(). +-type latin1_char() :: byte(). +-type latin1_chardata() :: latin1_charlist() | latin1_binary(). +-type latin1_charlist() :: [latin1_char() | latin1_binary() + | latin1_charlist()]. + +-spec characters_to_list(Data) -> Result when + Data :: latin1_chardata() | chardata() | external_chardata(), + Result :: list() + | {error, list(), RestData} + | {incomplete, list(), binary()}, + RestData :: latin1_chardata() | chardata() | external_chardata(). characters_to_list(ML) -> unicode:characters_to_list(ML,unicode). @@ -51,7 +73,7 @@ characters_to_list_int(ML, Encoding) -> _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML,Encoding])), erlang:raise(error,TheError,[{Mod,characters_to_list,L}|Rest]) @@ -69,6 +91,13 @@ do_characters_to_list(ML, Encoding) -> end. +-spec characters_to_binary(Data) -> Result when + Data :: latin1_chardata() | chardata() | external_chardata(), + Result :: binary() + | {error, binary(), RestData} + | {incomplete, binary(), binary()}, + RestData :: latin1_chardata() | chardata() | external_chardata(). + characters_to_binary(ML) -> try unicode:characters_to_binary(ML,unicode) @@ -80,7 +109,7 @@ characters_to_binary(ML) -> _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML])), erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest]) @@ -98,12 +127,21 @@ characters_to_binary_int(ML,InEncoding) -> _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML,InEncoding])), erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest]) end. +-spec characters_to_binary(Data, InEncoding, OutEncoding) -> Result when + Data :: latin1_chardata() | chardata() | external_chardata(), + InEncoding :: encoding(), + OutEncoding :: encoding(), + Result :: binary() + | {error, binary(), RestData} + | {incomplete, binary(), binary()}, + RestData :: latin1_chardata() | chardata() | external_chardata(). + characters_to_binary(ML, latin1, latin1) when is_binary(ML) -> ML; characters_to_binary(ML, latin1, Uni) when is_binary(ML) and ((Uni =:= utf8) or (Uni =:= unicode)) -> @@ -121,7 +159,7 @@ characters_to_binary(ML, latin1, Uni) when is_binary(ML) and ((Uni =:= utf8) or _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML,latin1,Uni])), erlang:raise(error,TheError, @@ -143,7 +181,7 @@ characters_to_binary(ML,Uni,latin1) when is_binary(ML) and ((Uni =:= utf8) or _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML,Uni,latin1])), erlang:raise(error,TheError, @@ -162,7 +200,7 @@ characters_to_binary(ML, InEncoding, OutEncoding) -> _ -> badarg end, - {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} = + {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} = (catch erlang:error(new_stacktrace, [ML,InEncoding,OutEncoding])), erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest]) @@ -215,6 +253,13 @@ characters_to_binary_int(ML, InEncoding, OutEncoding) -> Res end. +-spec bom_to_encoding(Bin) -> {Encoding, Length} when + Bin :: binary(), + Encoding :: 'latin1' | 'utf8' + | {'utf16', endian()} + | {'utf32', endian()}, + Length :: non_neg_integer(). + bom_to_encoding(<<239,187,191,_/binary>>) -> {utf8,3}; bom_to_encoding(<<0,0,254,255,_/binary>>) -> @@ -228,6 +273,10 @@ bom_to_encoding(<<255,254,_/binary>>) -> bom_to_encoding(Bin) when is_binary(Bin) -> {latin1,0}. +-spec encoding_to_bom(InEncoding) -> Bin when + Bin :: binary(), + InEncoding :: encoding(). + encoding_to_bom(unicode) -> <<239,187,191>>; encoding_to_bom(utf8) -> diff --git a/lib/stdlib/src/win32reg.erl b/lib/stdlib/src/win32reg.erl index ee0d17bc94..598e77ffdc 100644 --- a/lib/stdlib/src/win32reg.erl +++ b/lib/stdlib/src/win32reg.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -52,14 +52,17 @@ -define(reg_dword, 4). %% Basic types internal to this file. --type open_mode() :: 'read' | 'write'. --type reg_handle() :: {'win32reg',port()}. +-opaque reg_handle() :: {'win32reg',port()}. -type name() :: string() | 'default'. -type value() :: string() | integer() | binary(). %%% Exported functions. --spec open([open_mode()]) -> {'ok', reg_handle()} | {'error', 'enotsup'}. +-spec open(OpenModeList) -> ReturnValue when + OpenModeList :: [OpenMode], + OpenMode :: 'read' | 'write', + ReturnValue :: {'ok', RegHandle} | {'error', ErrorId :: 'enotsup'}, + RegHandle :: reg_handle(). open(Modes) -> case os:type() of @@ -75,14 +78,17 @@ open(Modes) -> {error, enotsup} end. --spec close(reg_handle()) -> 'ok'. +-spec close(RegHandle) -> 'ok' when + RegHandle :: reg_handle(). close({win32reg, Reg}) when is_port(Reg) -> unlink(Reg), exit(Reg, die), ok. --spec current_key(reg_handle()) -> {'ok', string()}. +-spec current_key(RegHandle) -> ReturnValue when + RegHandle :: reg_handle(), + ReturnValue :: {'ok', string()}. current_key({win32reg, Reg}) when is_port(Reg) -> Cmd = [?cmd_get_current], @@ -94,12 +100,18 @@ current_key({win32reg, Reg}) when is_port(Reg) -> _ -> Root ++ [$\\|Name] end}. --spec change_key(reg_handle(), string()) -> 'ok' | {'error', atom()}. +-spec change_key(RegHandle, Key) -> ReturnValue when + RegHandle :: reg_handle(), + Key :: string(), + ReturnValue :: 'ok' | {'error', ErrorId :: atom()}. change_key({win32reg, Reg}, Key) when is_port(Reg) -> change_key(Reg, ?cmd_open_key, Key). --spec change_key_create(reg_handle(), string()) -> 'ok' | {'error', atom()}. +-spec change_key_create(RegHandle, Key) -> ReturnValue when + RegHandle :: reg_handle(), + Key :: string(), + ReturnValue :: 'ok' | {'error', ErrorId :: atom()}. change_key_create({win32reg, Reg}, Key) when is_port(Reg) -> change_key(Reg, ?cmd_create_key, Key). @@ -113,21 +125,30 @@ change_key(Reg, Cmd, Key) -> {error, Reason} end. --spec sub_keys(reg_handle()) -> {'ok', [string()]} | {'error', atom()}. +-spec sub_keys(RegHandle) -> ReturnValue when + RegHandle :: reg_handle(), + ReturnValue :: {'ok', [SubKey]} | {'error', ErrorId :: atom()}, + SubKey :: string(). sub_keys({win32reg, Reg}) when is_port(Reg) -> Cmd = [?cmd_get_all_subkeys], Reg ! {self(), {command, Cmd}}, collect_keys(Reg, []). --spec delete_key(reg_handle()) -> 'ok' | {'error', atom()}. +-spec delete_key(RegHandle) -> ReturnValue when + RegHandle :: reg_handle(), + ReturnValue :: 'ok' | {'error', ErrorId :: atom()}. delete_key({win32reg, Reg}) when is_port(Reg) -> Cmd = [?cmd_delete_key], Reg ! {self(), {command, Cmd}}, get_result(Reg). --spec set_value(reg_handle(), name(), value()) -> 'ok' | {'error', atom()}. +-spec set_value(RegHandle, Name, Value) -> ReturnValue when + RegHandle :: reg_handle(), + Name :: name(), + Value :: value(), + ReturnValue :: 'ok' | {'error', ErrorId :: atom()}. set_value({win32reg, Reg}, Name0, Value) when is_port(Reg) -> Name = @@ -140,7 +161,10 @@ set_value({win32reg, Reg}, Name0, Value) when is_port(Reg) -> Reg ! {self(), {command, Cmd}}, get_result(Reg). --spec value(reg_handle(), name()) -> {'ok', value()} | {'error', atom()}. +-spec value(RegHandle, Name) -> ReturnValue when + RegHandle :: reg_handle(), + Name :: name(), + ReturnValue :: {'ok', Value :: value()} | {'error', ErrorId :: atom()}. value({win32reg, Reg}, Name) when is_port(Reg) -> Cmd = [?cmd_get_value, Name, 0], @@ -152,14 +176,20 @@ value({win32reg, Reg}, Name) when is_port(Reg) -> {error, Reason} end. --spec values(reg_handle()) -> {'ok', [{name(), value()}]} | {'error', atom()}. +-spec values(RegHandle) -> ReturnValue when + RegHandle :: reg_handle(), + ReturnValue :: {'ok', [ValuePair]} | {'error', ErrorId :: atom()}, + ValuePair :: {Name :: name(), Value :: value()}. values({win32reg, Reg}) when is_port(Reg) -> Cmd = [?cmd_get_all_values], Reg ! {self(), {command, Cmd}}, collect_values(Reg, []). --spec delete_value(reg_handle(), name()) -> 'ok' | {'error', atom()}. +-spec delete_value(RegHandle, Name) -> ReturnValue when + RegHandle :: reg_handle(), + Name :: name(), + ReturnValue :: 'ok' | {'error', ErrorId :: atom()}. delete_value({win32reg, Reg}, Name0) when is_port(Reg) -> Name = @@ -171,7 +201,9 @@ delete_value({win32reg, Reg}, Name0) when is_port(Reg) -> Reg ! {self(), {command, Cmd}}, get_result(Reg). --spec expand(string()) -> string(). +-spec expand(String) -> ExpandedString when + String :: string(), + ExpandedString :: string(). expand(Value) -> expand(Value, [], []). @@ -195,7 +227,9 @@ expand([C|Rest], Env, Result) -> expand([], [], Result) -> lists:reverse(Result). --spec format_error(atom()) -> string(). +-spec format_error(ErrorId) -> ErrorString when + ErrorId :: atom(), + ErrorString :: string(). format_error(ErrorId) -> erl_posix_msg:message(ErrorId). @@ -203,7 +237,7 @@ format_error(ErrorId) -> %%% Implementation. -spec collect_values(port(), [{name(), value()}]) -> - {'ok', [{name(), value()}]} | {'error', atom()}. + {'ok', [{name(), value()}]} | {'error', ErrorId :: atom()}. collect_values(P, Result) -> case get_result(P) of @@ -215,7 +249,7 @@ collect_values(P, Result) -> {error, Reason} end. --spec collect_keys(port(), string()) -> {'ok', [string()]} | {'error', atom()}. +-spec collect_keys(port(), string()) -> {'ok', [string()]} | {'error', ErrorId :: atom()}. collect_keys(P, Result) -> case get_result(P) of diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl index d41aeefa59..c82c8159b6 100644 --- a/lib/stdlib/src/zip.erl +++ b/lib/stdlib/src/zip.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -203,6 +203,9 @@ zip_comment_length}). +-type zip_file() :: #zip_file{}. +-type zip_comment() :: #zip_comment{}. + %% Open a zip archive with options %% @@ -220,7 +223,7 @@ openzip_open(F, Options) -> do_openzip_open(F, Options) -> Opts = get_openzip_options(Options), #openzip_opts{output = Output, open_opts = OpO, cwd = CWD} = Opts, - Input = get_zip_input(F), + Input = get_input(F), In0 = Input({open, F, OpO -- [write]}, []), {[#zip_comment{comment = C} | Files], In1} = get_central_dir(In0, fun raw_file_info_etc/5, Input), @@ -323,8 +326,33 @@ openzip_close(_) -> %% Accepted options: %% verbose, cooked, file_list, keep_old_files, file_filter, memory +-spec(unzip(Archive) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, FileList} + | {ok, FileBinList} + | {error, Reason :: term()} + | {error, {Name :: file:name(), Reason :: term()}}, + FileList :: [file:name()], + FileBinList :: [{file:name(),binary()}]). + unzip(F) -> unzip(F, []). +-spec(unzip(Archive, Options) -> RetValue when + Archive :: file:name() | binary(), + Options :: [Option], + Option :: {file_list, FileList} + | keep_old_files | verbose | memory | + {file_filter, FileFilter} | {cwd, CWD}, + FileList :: [file:name()], + FileBinList :: [{file:name(),binary()}], + FileFilter :: fun((ZipFile) -> boolean()), + CWD :: string(), + ZipFile :: zip_file(), + RetValue :: {ok, FileList} + | {ok, FileBinList} + | {error, Reason :: term()} + | {error, {Name :: file:name(), Reason :: term()}}). + unzip(F, Options) -> case ?CATCH do_unzip(F, Options) of {ok, R} -> {ok, R}; @@ -345,6 +373,18 @@ do_unzip(F, Options) -> {ok, Files}. %% Iterate over all files in a zip archive +-spec(foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason} when + Fun :: fun((FileInArchive, GetInfo, GetBin, AccIn) -> AccOut), + FileInArchive :: file:name(), + GetInfo :: fun(() -> file:file_info()), + GetBin :: fun(() -> binary()), + Acc0 :: term(), + Acc1 :: term(), + AccIn :: term(), + AccOut :: term(), + Archive :: file:name() | {file:name(), binary()}, + Reason :: term()). + foldl(Fun, Acc0, Archive) when is_function(Fun, 4) -> ZipFun = fun({Name, GetInfo, GetBin}, A) -> @@ -368,8 +408,33 @@ foldl(_,_, _) -> %% Accepted options: %% verbose, cooked, memory, comment +-spec(zip(Name, FileList) -> RetValue when + Name :: file:name(), + FileList :: [FileSpec], + FileSpec :: file:name() | {file:name(), binary()} + | {file:name(), binary(), file:file_info()}, + RetValue :: {ok, FileName :: file:name()} + | {ok, {FileName :: file:name(), binary()}} + | {error, Reason :: term()}). + zip(F, Files) -> zip(F, Files, []). +-spec(zip(Name, FileList, Options) -> RetValue when + Name :: file:name(), + FileList :: [FileSpec], + FileSpec :: file:name() | {file:name(), binary()} + | {file:name(), binary(), file:file_info()}, + Options :: [Option], + Option :: memory | cooked | verbose | {comment, Comment} + | {cwd, CWD} | {compress, What} | {uncompress, What}, + What :: all | [Extension] | {add, [Extension]} | {del, [Extension]}, + Extension :: string(), + Comment :: string(), + CWD :: string(), + RetValue :: {ok, FileName :: file:name()} + | {ok, {FileName :: file:name(), binary()}} + | {error, Reason :: term()}). + zip(F, Files, Options) -> case ?CATCH do_zip(F, Files, Options) of {ok, R} -> {ok, R}; @@ -392,8 +457,20 @@ do_zip(F, Files, Options) -> %% Accepted options: %% cooked, file_filter, file_output (latter 2 undocumented) +-spec(list_dir(Archive) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, + CommentAndFiles :: [zip_comment() | zip_file()]). + list_dir(F) -> list_dir(F, []). +-spec(list_dir(Archive, Options) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, + CommentAndFiles :: [zip_comment() | zip_file()], + Options :: [Option], + Option :: cooked). + list_dir(F, Options) -> case ?CATCH do_list_dir(F, Options) of {ok, R} -> {ok, R}; @@ -411,6 +488,10 @@ do_list_dir(F, Options) -> %% Print zip directory in short form +-spec(t(Archive) -> ok when + Archive :: file:name() | binary() | ZipHandle, + ZipHandle :: pid()). + t(F) when is_pid(F) -> zip_t(F); t(F) when is_record(F, openzip) -> openzip_t(F); t(F) -> t(F, fun raw_short_print_info_etc/5). @@ -431,6 +512,10 @@ do_t(F, RawPrint) -> %% Print zip directory in long form (like ls -l) +-spec(tt(Archive) -> ok when + Archive :: file:name() | binary() | ZipHandle, + ZipHandle :: pid()). + tt(F) when is_pid(F) -> zip_tt(F); tt(F) when is_record(F, openzip) -> openzip_tt(F); tt(F) -> t(F, fun raw_long_print_info_etc/5). @@ -605,11 +690,78 @@ get_list_dir_options(F, Options) -> get_list_dir_opt(Options, Opts). %% aliases for erl_tar compatibility +-spec(table(Archive) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, + CommentAndFiles :: [zip_comment() | zip_file()]). + table(F) -> list_dir(F). + +-spec(table(Archive, Options) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, + CommentAndFiles :: [zip_comment() | zip_file()], + + Options :: [Option], + Option :: cooked). + table(F, O) -> list_dir(F, O). + +-spec(create(Name, FileList) -> RetValue when + Name :: file:name(), + FileList :: [FileSpec], + FileSpec :: file:name() | {file:name(), binary()} + | {file:name(), binary(), file:file_info()}, + RetValue :: {ok, FileName :: file:name()} + | {ok, {FileName :: file:name(), binary()}} + | {error, Reason :: term()}). + create(F, Fs) -> zip(F, Fs). + +-spec(create(Name, FileList, Options) -> RetValue when + Name :: file:name(), + FileList :: [FileSpec], + FileSpec :: file:name() | {file:name(), binary()} + | {file:name(), binary(), file:file_info()}, + Options :: [Option], + Option :: memory | cooked | verbose | {comment, Comment} + | {cwd, CWD} | {compress, What} | {uncompress, What}, + What :: all | [Extension] | {add, [Extension]} | {del, [Extension]}, + Extension :: string(), + Comment :: string(), + CWD :: string(), + RetValue :: {ok, FileName :: file:name()} + | {ok, {FileName :: file:name(), binary()}} + | {error, Reason :: term()}). create(F, Fs, O) -> zip(F, Fs, O). + +-spec(extract(Archive) -> RetValue when + Archive :: file:name() | binary(), + RetValue :: {ok, FileList} + | {ok, FileBinList} + | {error, Reason :: term()} + | {error, {Name :: file:name(), Reason :: term()}}, + FileList :: [file:name()], + FileBinList :: [{file:name(),binary()}]). + extract(F) -> unzip(F). + +-spec(extract(Archive, Options) -> RetValue when + Archive :: file:name() | binary(), + Options :: [Option], + Option :: {file_list, FileList} + | keep_old_files | verbose | memory | + {file_filter, FileFilter} | {cwd, CWD}, + FileList :: [file:name()], + FileBinList :: [{file:name(),binary()}], + FileFilter :: fun((ZipFile) -> boolean()), + CWD :: string(), + ZipFile :: zip_file(), + RetValue :: {ok, FileList} + | {ok, FileBinList} + | {error, Reason :: term()} + | {error, {Name :: file:name(), Reason :: term()}}). + extract(F, O) -> unzip(F, O). @@ -990,21 +1142,52 @@ server_loop(OpenZip) -> {error, bad_msg} end. +-spec(zip_open(Archive) -> {ok, ZipHandle} | {error, Reason} when + Archive :: file:name() | binary(), + ZipHandle :: pid(), + Reason :: term()). + zip_open(Archive) -> zip_open(Archive, []). +-spec(zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason} when + Archive :: file:name() | binary(), + ZipHandle :: pid(), + Options :: [Option], + Option :: cooked | memory | {cwd, CWD :: string()}, + Reason :: term()). + zip_open(Archive, Options) -> Pid = spawn(fun() -> server_loop(not_open) end), request(self(), Pid, {open, Archive, Options}). +-spec(zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason} when + ZipHandle :: pid(), + Result :: file:name() | {file:name(), binary()}, + Reason :: term()). + zip_get(Pid) when is_pid(Pid) -> request(self(), Pid, get). +-spec(zip_close(ZipHandle) -> ok | {error, einval} when + ZipHandle :: pid()). + zip_close(Pid) when is_pid(Pid) -> request(self(), Pid, close). +-spec(zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason} when + FileName :: file:name(), + ZipHandle :: pid(), + Result :: file:name() | {file:name(), binary()}, + Reason :: term()). + zip_get(FileName, Pid) when is_pid(Pid) -> request(self(), Pid, {get, FileName}). +-spec(zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason} when + Result :: [zip_comment() | zip_file()], + ZipHandle :: pid(), + Reason :: term()). + zip_list_dir(Pid) when is_pid(Pid) -> request(self(), Pid, list_dir). diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index 3dd0a91870..5502c69fa5 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -135,7 +135,7 @@ release_tests_spec: make_emakefile $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DATA) stdlib.spec $(EMAKEFILE) \ $(ERL_FILES) $(COVERFILE) $(RELSYSDIR) - chmod -f -R u+w $(RELSYSDIR) + chmod -R u+w $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) release_docs_spec: diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl index 4ccc863795..5df19ca7f1 100644 --- a/lib/stdlib/test/beam_lib_SUITE.erl +++ b/lib/stdlib/test/beam_lib_SUITE.erl @@ -181,7 +181,8 @@ error(Conf) when is_list(Conf) -> ?line verify(not_a_beam_file, beam_lib:info(<<"short">>)), ?line {Binary1, _} = split_binary(Binary, byte_size(Binary)-10), - ?line verify(chunk_too_big, beam_lib:chunks(Binary1, ["Abst"])), + LastChunk = last_chunk(Binary), + ?line verify(chunk_too_big, beam_lib:chunks(Binary1, [LastChunk])), ?line Chunks = chunk_info(Binary), ?line {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks), ?line {Binary2, _} = split_binary(Binary, AbstractStart), @@ -205,6 +206,12 @@ error(Conf) when is_list(Conf) -> ?line file:delete(ACopy), ok. +last_chunk(Bin) -> + L = beam_lib:info(Bin), + {chunks,Chunks} = lists:keyfind(chunks, 1, L), + {Last,_,_} = lists:last(Chunks), + Last. + do_error(BeamFile, ACopy) -> % evil tests ?line Chunks = chunk_info(BeamFile), @@ -242,8 +249,8 @@ cmp(doc) -> ["Compare contents of BEAM files and directories"]; cmp(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, dir1), - ?line Dir2 = filename:join(PrivDir, dir2), + ?line Dir1 = filename:join(PrivDir, "dir1"), + ?line Dir2 = filename:join(PrivDir, "dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -292,8 +299,8 @@ cmp_literals(doc) -> ["Compare contents of BEAM files having literals"]; cmp_literals(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, dir1), - ?line Dir2 = filename:join(PrivDir, dir2), + ?line Dir1 = filename:join(PrivDir, "dir1"), + ?line Dir2 = filename:join(PrivDir, "dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -330,6 +337,7 @@ strip(Conf) when is_list(Conf) -> ?line {Source2D1, BeamFile2D1} = make_beam(PrivDir, simple2, concat), ?line {Source3D1, BeamFile3D1} = make_beam(PrivDir, make_fun, make_fun), ?line {Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant), + ?line {Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines), ?line NoOfTables = length(ets:all()), ?line P0 = pps(), @@ -360,13 +368,25 @@ strip(Conf) when is_list(Conf) -> ?line {module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)), ?line {module, constant} = code:load_abs(filename:rootname(BeamFile4D1)), + %% check that line number information is still present after stripping + ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)), + ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} = + (catch lines:t(atom)), + ?line true = code:delete(lines), + ?line false = code:purge(lines), + ?line {ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1), + ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)), + ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} = + (catch lines:t(atom)), + ?line true = (P0 == pps()), ?line NoOfTables = length(ets:all()), ?line delete_files([SourceD1, BeamFileD1, Source2D1, BeamFile2D1, Source3D1, BeamFile3D1, - Source4D1, BeamFile4D1]), + Source4D1, BeamFile4D1, + Source5D1, BeamFile5D1]), ok. @@ -381,7 +401,7 @@ otp_6711(Conf) when is_list(Conf) -> (catch {a, beam_lib:strip_files([3])}), ?line PrivDir = ?privdir, - ?line Dir = filename:join(PrivDir, dir), + ?line Dir = filename:join(PrivDir, "dir"), ?line Lib = filename:join(Dir, "lib"), ?line App = filename:join(Lib, "app"), ?line EBin = filename:join(App, "ebin"), @@ -417,8 +437,8 @@ building(doc) -> "Testing building of BEAM files."; building(Conf) when is_list(Conf) -> ?line PrivDir = ?privdir, - ?line Dir1 = filename:join(PrivDir, b_dir1), - ?line Dir2 = filename:join(PrivDir, b_dir2), + ?line Dir1 = filename:join(PrivDir, "b_dir1"), + ?line Dir2 = filename:join(PrivDir, "b_dir2"), ok = file:make_dir(Dir1), ok = file:make_dir(Dir2), @@ -571,8 +591,18 @@ do_encrypted_abstr(Beam, Key) -> ?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]), ?line {ok,cleared} = beam_lib:clear_crypto_key_fun(), + + %% Try to force a stop/start race. + ?line start_stop_race(10000), + ok. +start_stop_race(0) -> + ok; +start_stop_race(N) -> + {error,_} = beam_lib:crypto_key_fun(bad_fun), + undefined = beam_lib:clear_crypto_key_fun(), + start_stop_race(N-1). bad_fun(F) -> {error,E} = beam_lib:crypto_key_fun(F), @@ -688,7 +718,7 @@ chunk_info(File) -> Chunks. make_beam(Dir, Module, F) -> - ?line FileBase = filename:join(Dir, Module), + ?line FileBase = filename:join(Dir, atom_to_list(Module)), ?line Source = FileBase ++ ".erl", ?line BeamFile = FileBase ++ ".beam", ?line simple_file(Source, Module, F), @@ -773,6 +803,12 @@ simple_file(File, Module, constant2) -> "t(A) -> " " {a,b,[2,3],x,y}. "]), ok = file:write_file(File, B); +simple_file(File, Module, lines) -> + B = list_to_binary(["-module(", atom_to_list(Module), ").\n" + "-export([t/1]).\n" + "t(A) ->\n" + " A+1.\n"]), + ok = file:write_file(File, B); simple_file(File, Module, F) -> B = list_to_binary(["-module(", atom_to_list(Module), "). " "-export([t/0]). " diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 9fcc9e6aaf..63767aeda6 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -34,6 +34,8 @@ -define(datadir(Conf), ?config(data_dir, Conf)). -endif. +-compile(r13). % OTP-9607 + -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, not_run/1, newly_started/1, basic_v8/1, basic_v9/1, @@ -53,7 +55,7 @@ simultaneous_open/1, insert_new/1, repair_continuation/1, otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1, otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1, - otp_8923/1]). + otp_8923/1, otp_9282/1, otp_9607/1]). -export([dets_dirty_loop/0]). @@ -112,7 +114,7 @@ all() -> many_clients, otp_4906, otp_5402, simultaneous_open, insert_new, repair_continuation, otp_5487, otp_6206, otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898, - otp_8899, otp_8903, otp_8923] + otp_8899, otp_8903, otp_8923, otp_9282, otp_9607] end. groups() -> @@ -554,7 +556,11 @@ dets_dirty_loop() -> {From, [write, Name, Value]} -> Ret = dets:insert(Name, Value), From ! {self(), Ret}, - dets_dirty_loop() + dets_dirty_loop(); + {From, [close, Name]} -> + Ret = dets:close(Name), + From ! {self(), Ret}, + dets_dirty_loop() end. @@ -1516,7 +1522,7 @@ repair(Config, V) -> if V =:= 8 -> %% first estimated number of objects is wrong, repair once more - ?line {ok, Fd} = file:open(Fname, read_write), + ?line {ok, Fd} = file:open(Fname, [read,write]), NoPos = HeadSize - 8, % no_objects ?line file:pwrite(Fd, NoPos, <<0:32>>), % NoItems ok = file:close(Fd), @@ -1568,8 +1574,10 @@ repair(Config, V) -> ?line FileSize = dets:info(TabRef, memory), ?line ok = dets:close(TabRef), crash(Fname, FileSize+20), - ?line {error, {bad_freelists, Fname}} = + %% Used to return bad_freelists, but that changed in OTP-9622 + ?line {ok, TabRef} = dets:open_file(TabRef, [{file,Fname},{version,V}]), + ?line ok = dets:close(TabRef), ?line file:delete(Fname), %% File not closed, opening with read and read_write access tried. @@ -1857,9 +1865,9 @@ fixtable(Config, Version) when is_list(Config) -> ?line {ok, _} = dets:open_file(T, Args), %% badarg - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:safe_fixtable(no_table,true)), - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined],_}|_]}} = (catch dets:safe_fixtable(T,undefined)), %% The table is not allowed to grow while the elements are inserted: @@ -1940,21 +1948,21 @@ match(Config, Version) -> %% match, badarg MSpec = [{'_',[],['$_']}], - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:match(no_table, '_')), - ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number]}|_]}} = + ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number],_}|_]}} = (catch dets:match(T, '_', not_a_number)), ?line {EC1, _} = dets:select(T, MSpec, 1), - ?line {'EXIT', {badarg, [{dets,match,[EC1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,match,[EC1],_}|_]}} = (catch dets:match(EC1)), %% match_object, badarg - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:match_object(no_table, '_')), - ?line {'EXIT', {badarg, [{dets,match_object,[T,'_',not_a_number]}|_]}} = + ?line {'EXIT', {badarg, [{dets,match_object,[T,'_',not_a_number],_}|_]}} = (catch dets:match_object(T, '_', not_a_number)), ?line {EC2, _} = dets:select(T, MSpec, 1), - ?line {'EXIT', {badarg, [{dets,match_object,[EC2]}|_]}} = + ?line {'EXIT', {badarg, [{dets,match_object,[EC2],_}|_]}} = (catch dets:match_object(EC2)), dets:safe_fixtable(T, true), @@ -2118,16 +2126,16 @@ select(Config, Version) -> %% badarg MSpec = [{'_',[],['$_']}], - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:select(no_table, MSpec)), - ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>]}|_]}} = + ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>],_}|_]}} = (catch dets:select(T, <<17>>)), - ?line {'EXIT', {badarg, [{dets,select,[T,[]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,select,[T,[]],_}|_]}} = (catch dets:select(T, [])), - ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number]}|_]}} = + ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number],_}|_]}} = (catch dets:select(T, MSpec, not_a_number)), ?line {EC, _} = dets:match(T, '_', 1), - ?line {'EXIT', {badarg, [{dets,select,[EC]}|_]}} = + ?line {'EXIT', {badarg, [{dets,select,[EC],_}|_]}} = (catch dets:select(EC)), AllSpec = [{'_',[],['$_']}], @@ -2210,7 +2218,7 @@ update_counter(Config) when is_list(Config) -> ?line file:delete(Fname), P0 = pps(), - ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1],_}|_]}} = (catch dets:update_counter(no_table, 1, 1)), Args = [{file,Fname},{keypos,2}], @@ -2254,65 +2262,66 @@ badarg(Config) when is_list(Config) -> %% badargs are tested in match, select and fixtable too. %% open - ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple},[]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple},[]],_}|_]}} = (catch dets:open_file({a,tuple},[])), - ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple}]}|_]}} = + ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple}],_}|_]}} = (catch dets:open_file({a,tuple})), - ?line {'EXIT', {badarg, [{dets,open_file,[file,[foo]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,open_file,[file,[foo]],_}|_]}} = (catch dets:open_file(file,[foo])), - ?line {'EXIT', {badarg,[{dets,open_file,[{hej,san},[{type,set}|3]]}|_]}} = + ?line {'EXIT', {badarg,[{dets,open_file, + [{hej,san},[{type,set}|3]],_}|_]}} = (catch dets:open_file({hej,san},[{type,set}|3])), %% insert - ?line {'EXIT', {badarg, [{dets,insert,[no_table,{1,2}]}|_]}} = + ?line {'EXIT', {badarg, [{dets,insert,[no_table,{1,2}],_}|_]}} = (catch dets:insert(no_table, {1,2})), - ?line {'EXIT', {badarg, [{dets,insert,[no_table,[{1,2}]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,insert,[no_table,[{1,2}]],_}|_]}} = (catch dets:insert(no_table, [{1,2}])), - ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}]}|_]}} = + ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}],_}|_]}} = (catch dets:insert(T, {1,2})), - ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2}]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2}]],_}|_]}} = (catch dets:insert(T, [{1,2}])), - ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2,3}|3]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2,3}|3]],_}|_]}} = (catch dets:insert(T, [{1,2,3} | 3])), %% lookup{_keys} - ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]],_}|_]}} = (catch dets:lookup_keys(T, [])), - ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1],_}|_]}} = (catch dets:lookup(no_table, 1)), - ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]],_}|_]}} = (catch dets:lookup_keys(T, [1 | 2])), %% member - ?line {'EXIT', {badarg, [{dets,member,[no_table,1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,member,[no_table,1],_}|_]}} = (catch dets:member(no_table, 1)), %% sync - ?line {'EXIT', {badarg, [{dets,sync,[no_table]}|_]}} = + ?line {'EXIT', {badarg, [{dets,sync,[no_table],_}|_]}} = (catch dets:sync(no_table)), %% delete{_keys} - ?line {'EXIT', {badarg, [{dets,delete,[no_table,1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete,[no_table,1],_}|_]}} = (catch dets:delete(no_table, 1)), %% delete_object - ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,{1,2,3}]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,{1,2,3}],_}|_]}} = (catch dets:delete_object(no_table, {1,2,3})), - ?line {'EXIT', {badarg, [{dets,delete_object,[T,{1,2}]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_object,[T,{1,2}],_}|_]}} = (catch dets:delete_object(T, {1,2})), - ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,[{1,2,3}]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,[{1,2,3}]],_}|_]}} = (catch dets:delete_object(no_table, [{1,2,3}])), - ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2}]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2}]],_}|_]}} = (catch dets:delete_object(T, [{1,2}])), - ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]],_}|_]}} = (catch dets:delete_object(T, [{1,2,3} | 3])), %% first,next,slot - ?line {'EXIT', {badarg, [{dets,first,[no_table]}|_]}} = + ?line {'EXIT', {badarg, [{dets,first,[no_table],_}|_]}} = (catch dets:first(no_table)), - ?line {'EXIT', {badarg, [{dets,next,[no_table,1]}|_]}} = + ?line {'EXIT', {badarg, [{dets,next,[no_table,1],_}|_]}} = (catch dets:next(no_table, 1)), - ?line {'EXIT', {badarg, [{dets,slot,[no_table,0]}|_]}} = + ?line {'EXIT', {badarg, [{dets,slot,[no_table,0],_}|_]}} = (catch dets:slot(no_table, 0)), %% info @@ -2321,26 +2330,26 @@ badarg(Config) when is_list(Config) -> ?line undefined = dets:info(T, foo), %% match_delete - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:match_delete(no_table, '_')), %% delete_all_objects - ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table]}|_]}} = + ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table],_}|_]}} = (catch dets:delete_all_objects(no_table)), %% select_delete MSpec = [{'_',[],['$_']}], - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:select_delete(no_table, MSpec)), - ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>]}|_]}} = + ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>],_}|_]}} = (catch dets:select_delete(T, <<17>>)), %% traverse, fold - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:traverse(no_table, fun(_) -> continue end)), - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:foldl(fun(_, A) -> A end, [], no_table)), - ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} = + ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} = (catch dets:foldr(fun(_, A) -> A end, [], no_table)), %% close @@ -2349,14 +2358,14 @@ badarg(Config) when is_list(Config) -> ?line {error, not_owner} = dets:close(T), %% init_table - ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} = + ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]],_}|_]}} = (catch dets:init_table(no_table, fun(X) -> X end)), - ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} = + ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]],_}|_]}} = (catch dets:init_table(no_table, fun(X) -> X end, [])), %% from_ets Ets = ets:new(ets,[]), - ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_]}|_]}} = + ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_],_}|_]}} = (catch dets:from_ets(no_table, Ets)), ets:delete(Ets), @@ -3247,7 +3256,7 @@ otp_5402(suite) -> []; otp_5402(Config) when is_list(Config) -> Tab = otp_5402, - ?line File = filename:join([cannot, write, this, file]), + ?line File = filename:join(["cannot", "write", "this", "file"]), %% close ?line{ok, T} = dets:open_file(Tab, [{ram_file,true}, @@ -3857,15 +3866,118 @@ otp_8923(Config) when is_list(Config) -> file:delete(File), ok. +otp_9282(doc) -> + ["OTP-9282. The name of a table can be an arbitrary term"]; +otp_9282(suite) -> + []; +otp_9282(Config) when is_list(Config) -> + some_calls(make_ref(), Config), + some_calls({a,typical,name}, Config), + some_calls(fun() -> a_funny_name end, Config), + ok. + +some_calls(Tab, Config) -> + File = filename(ref, Config), + ?line {ok,T} = dets:open_file(Tab, [{file,File}]), + ?line T = Tab, + ?line false = dets:info(T, safe_fixed), + ?line File = dets:info(T, filename), + ?line ok = dets:insert(Tab, [{3,0}]), + ?line [{3,0}] = dets:lookup(Tab, 3), + ?line [{3,0}] = dets:traverse(Tab, fun(X) -> {continue, X} end), + ?line ok = dets:close(T), + file:delete(File). + +otp_9607(doc) -> + ["OTP-9607. Test downgrading the slightly changed format."]; +otp_9607(suite) -> + []; +otp_9607(Config) when is_list(Config) -> + %% Note: the bug is about almost full tables. The fix of that + %% problem is *not* tested here. + Version = r13b, + case ?t:is_release_available(atom_to_list(Version)) of + true -> + T = otp_9607, + File = filename(T, Config), + Key = a, + Value = 1, + Args = [{file,File}], + ?line {ok, T} = dets:open_file(T, Args), + ?line ok = dets:insert(T, {Key, Value}), + ?line ok = dets:close(T), + + ?line Call = fun(P, A) -> + P ! {self(), A}, + receive + {P, Ans} -> + Ans + after 5000 -> + exit(other_process_dead) + end + end, + %% Create a file on the modified format, read the file + %% with an emulator that doesn't know about the modified + %% format. + ?line {ok, Node} = start_node_rel(Version, Version, slave), + ?line Pid = rpc:call(Node, erlang, spawn, + [?MODULE, dets_dirty_loop, []]), + ?line {error,{needs_repair, File}} = + Call(Pid, [open, T, Args++[{repair,false}]]), + io:format("Expect repair:~n"), + ?line {ok, T} = Call(Pid, [open, T, Args]), + ?line [{Key,Value}] = Call(Pid, [read, T, Key]), + ?line ok = Call(Pid, [close, T]), + file:delete(File), + + %% Create a file on the unmodified format. Modify the file + %% using an emulator that must not turn the file into the + %% modified format. Read the file and make sure it is not + %% repaired. + ?line {ok, T} = Call(Pid, [open, T, Args]), + ?line ok = Call(Pid, [write, T, {Key,Value}]), + ?line [{Key,Value}] = Call(Pid, [read, T, Key]), + ?line ok = Call(Pid, [close, T]), + + Key2 = b, + Value2 = 2, + + ?line {ok, T} = dets:open_file(T, Args), + ?line [{Key,Value}] = dets:lookup(T, Key), + ?line ok = dets:insert(T, {Key2,Value2}), + ?line ok = dets:close(T), + + ?line {ok, T} = Call(Pid, [open, T, Args++[{repair,false}]]), + ?line [{Key2,Value2}] = Call(Pid, [read, T, Key2]), + ?line ok = Call(Pid, [close, T]), + + ?t:stop_node(Node), + file:delete(File), + ok; + false -> + {skipped, "No support for old node"} + end. + + + %% %% Parts common to several test cases %% +start_node_rel(Name, Rel, How) -> + Release = [{release, atom_to_list(Rel)}], + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line test_server:start_node(Name, How, + [{args, + " -kernel net_setuptime 100 " + " -pa " ++ Pa}, + {erl, Release}]). + crash(File, Where) -> crash(File, Where, 10). crash(File, Where, What) when is_integer(What) -> - ?line {ok, Fd} = file:open(File, read_write), + ?line {ok, Fd} = file:open(File, [read,write]), ?line file:position(Fd, Where), ?line ok = file:write(Fd, [What]), ?line ok = file:close(Fd). @@ -4009,7 +4121,7 @@ writable(Fname) -> ?line file:write_file_info(Fname, Info#file_info{mode = Mode}). truncate(File, Where) -> - ?line {ok, Fd} = file:open(File, read_write), + ?line {ok, Fd} = file:open(File, [read,write]), ?line file:position(Fd, Where), ?line ok = file:truncate(Fd), ?line ok = file:close(Fd). diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index 9b024a5b49..57f3f4eddb 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -1280,7 +1280,7 @@ eval_tests(Config, Fun, Tests) -> check_test(Config, Test) -> - Filename = 'epp_test.erl', + Filename = "epp_test.erl", ?line PrivDir = ?config(priv_dir, Config), ?line File = filename:join(PrivDir, Filename), ?line ok = file:write_file(File, Test), @@ -1293,7 +1293,7 @@ check_test(Config, Test) -> compile_test(Config, Test0) -> Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0], - Filename = 'epp_test.erl', + Filename = "epp_test.erl", ?line PrivDir = ?config(priv_dir, Config), ?line File = filename:join(PrivDir, Filename), ?line ok = file:write_file(File, Test), diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 4b59cee99e..784c7cb86e 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1189,7 +1189,7 @@ lfh() -> {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}. local_func(F, As0, Bs0) when is_atom(F) -> - {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}), + {As,Bs} = erl_eval:expr_list(As0, Bs0, lfh()), case erlang:function_exported(?MODULE, F, length(As)) of true -> {value,apply(?MODULE, F, As),Bs}; @@ -1199,7 +1199,7 @@ local_func(F, As0, Bs0) when is_atom(F) -> lfh_value_extra() -> %% Not documented. - {value, fun(F, As) -> local_func_value(F, As) end, []}. + {value, fun(F, As, a1, a2) -> local_func_value(F, As) end, [a1, a2]}. lfh_value() -> {value, fun(F, As) -> local_func_value(F, As) end}. diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index f980d52e4e..9041adbe5c 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2981,7 +2981,7 @@ run_test(Conf, Test0, Warnings0) -> run_test2(Conf, Test, Warnings0). run_test2(Conf, Test, Warnings0) -> - Filename = 'lint_test.erl', + Filename = "lint_test.erl", DataDir = ?privdir, File = filename:join(DataDir, Filename), Opts = case Warnings0 of diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index bc811355ab..280c95b1aa 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -1161,7 +1161,7 @@ parse_forms2(String, Cont0, Line, Forms) -> {done, {ok, Tokens, EndLine}, Chars} -> {ok, Form} = erl_parse:parse_form(Tokens), parse_forms2(Chars, [], EndLine, [Form | Forms]); - {more, Cont} when element(3, Cont) =:= [] -> + {more, Cont} when element(4, Cont) =:= [] -> %% extra spaces after forms... parse_forms2([], Cont, Line, Forms); {more, Cont} -> diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl index 31a4f94294..4298b2c701 100644 --- a/lib/stdlib/test/erl_scan_SUITE.erl +++ b/lib/stdlib/test/erl_scan_SUITE.erl @@ -737,6 +737,10 @@ set_attribute() -> (catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error ?line {'EXIT',{badarg,_}} = (catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error + + %% OTP-9412 + ?line 8 = erl_scan:set_attribute(line, [{line,{nos,'X',8}}], + fun({nos,_V,VL}) -> VL end), ok. column_errors() -> diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 9d348b5f1a..e048764a55 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -72,6 +72,7 @@ exit_many_many_tables_owner/1]). -export([write_concurrency/1, heir/1, give_away/1, setopts/1]). -export([bad_table/1, types/1]). +-export([otp_9423/1]). -export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing @@ -143,7 +144,8 @@ all() -> otp_8166, exit_large_table_owner, exit_many_large_table_owner, exit_many_tables_owner, exit_many_many_tables_owner, write_concurrency, heir, - give_away, setopts, bad_table, types]. + give_away, setopts, bad_table, types, + otp_9423]. groups() -> [{new, [], @@ -793,16 +795,16 @@ t_ets_dets(Config, Opts) -> ?line true = ets:from_dets(ETab,DTab), ?line 3000 = ets:info(ETab,size), ?line ets:delete(ETab), - ?line {'EXIT',{badarg,[{ets,to_dets,[ETab,DTab]}|_]}} = + ?line {'EXIT',{badarg,[{ets,to_dets,[ETab,DTab],_}|_]}} = (catch ets:to_dets(ETab,DTab)), - ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab]}|_]}} = + ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab],_}|_]}} = (catch ets:from_dets(ETab,DTab)), ?line ETab2 = ets_new(x,Opts), ?line filltabint(ETab2,3000), ?line dets:close(DTab), - ?line {'EXIT',{badarg,[{ets,to_dets,[ETab2,DTab]}|_]}} = + ?line {'EXIT',{badarg,[{ets,to_dets,[ETab2,DTab],_}|_]}} = (catch ets:to_dets(ETab2,DTab)), - ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab]}|_]}} = + ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab],_}|_]}} = (catch ets:from_dets(ETab2,DTab)), ?line ets:delete(ETab2), ?line (catch file:delete(Fname)), @@ -817,6 +819,14 @@ t_delete_all_objects(Config) when is_list(Config) -> repeat_for_opts(t_delete_all_objects_do), ?line verify_etsmem(EtsMem). +get_kept_objects(T) -> + case ets:info(T,stats) of + false -> + 0; + {_,_,_,_,_,_,KO} -> + KO + end. + t_delete_all_objects_do(Opts) -> ?line T=ets_new(x,Opts), ?line filltabint(T,4000), @@ -826,10 +836,10 @@ t_delete_all_objects_do(Opts) -> ?line true = ets:delete_all_objects(T), ?line '$end_of_table' = ets:next(T,O), ?line 0 = ets:info(T,size), - ?line 4000 = ets:info(T,kept_objects), + ?line 4000 = get_kept_objects(T), ?line ets:safe_fixtable(T,false), ?line 0 = ets:info(T,size), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), ?line filltabint(T,4000), ?line 4000 = ets:info(T,size), ?line true = ets:delete_all_objects(T), @@ -859,10 +869,10 @@ t_delete_object_do(Opts) -> ?line ets:delete_object(T,{First, integer_to_list(First)}), ?line Next = ets:next(T,First), ?line 3999 = ets:info(T,size), - ?line 1 = ets:info(T,kept_objects), + ?line 1 = get_kept_objects(T), ?line ets:safe_fixtable(T,false), ?line 3999 = ets:info(T,size), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), ?line ets:delete(T), ?line T1 = ets_new(x,[ordered_set | Opts]), ?line filltabint(T1,4000), @@ -2642,7 +2652,7 @@ maybe_sort(L) when is_list(L) -> %maybe_sort({'EXIT',{Reason, [{Module, Function, _}|_]}}) -> % {'EXIT',{Reason, [{Module, Function, '_'}]}}; maybe_sort({'EXIT',{Reason, List}}) when is_list(List) -> - {'EXIT',{Reason, lists:map(fun({Module, Function, _}) -> + {'EXIT',{Reason, lists:map(fun({Module, Function, _, _}) -> {Module, Function, '_'} end, List)}}; @@ -2715,7 +2725,8 @@ ordered_do(Opts) -> 9,10,11,12, 1,2,3,4, 17,18,19,20, - 13,14,15,16 + 13,14,15,16, + 1 bsl 33 ], ?line lists:foreach(fun(X) -> ets:insert(T,{X,integer_to_list(X)}) @@ -2730,13 +2741,14 @@ ordered_do(Opts) -> ?line S2 = L2, ?line [{1,"1"}] = ets:slot(T,0), ?line [{28,"28"}] = ets:slot(T,27), + ?line [{1 bsl 33,_}] = ets:slot(T,28), ?line 27 = ets:prev(T,28), ?line [{7,"7"}] = ets:slot(T,6), - ?line '$end_of_table' = ets:next(T,28), + ?line '$end_of_table' = ets:next(T,1 bsl 33), ?line [{12,"12"}] = ets:slot(T,11), - ?line '$end_of_table' = ets:slot(T,28), + ?line '$end_of_table' = ets:slot(T,29), ?line [{1,"1"}] = ets:slot(T,0), - ?line 28 = ets:prev(T,29), + ?line 28 = ets:prev(T,1 bsl 33), ?line 1 = ets:next(T,0), ?line pick_all_forward(T), ?line [{7,"7"}] = ets:slot(T,6), @@ -4967,7 +4979,7 @@ grow_pseudo_deleted_do(Type) -> [true]}]), Left = Mult*(Mod-1), ?line Left = ets:info(T,size), - ?line Mult = ets:info(T,kept_objects), + ?line Mult = get_kept_objects(T), filltabstr(T,Mult), spawn_opt(fun()-> ?line true = ets:info(T,fixed), Self ! start, @@ -4981,7 +4993,7 @@ grow_pseudo_deleted_do(Type) -> ?line true = ets:safe_fixtable(T,false), io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]), ?line false = ets:info(T,fixed), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), ?line done = receive_any(), %%verify_table_load(T), % may fail if concurrency is poor (genny) ets:delete(T), @@ -5008,7 +5020,7 @@ shrink_pseudo_deleted_do(Type) -> [{'>', '$1', Half}], [true]}]), ?line Half = ets:info(T,size), - ?line Half = ets:info(T,kept_objects), + ?line Half = get_kept_objects(T), spawn_opt(fun()-> ?line true = ets:info(T,fixed), Self ! start, io:format("Starting to delete... ~p\n",[now()]), @@ -5021,7 +5033,7 @@ shrink_pseudo_deleted_do(Type) -> ?line true = ets:safe_fixtable(T,false), io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]), ?line false = ets:info(T,fixed), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), ?line done = receive_any(), %%verify_table_load(T), % may fail if concurrency is poor (genny) ets:delete(T), @@ -5137,7 +5149,7 @@ smp_fixed_delete_do() -> ?line 0 = ets:info(T,size), ?line true = ets:info(T,fixed), ?line Buckets = num_of_buckets(T), - ?line NumOfObjs = ets:info(T,kept_objects), + ?line NumOfObjs = get_kept_objects(T), ets:safe_fixtable(T,false), %% Will fail as unfix does not shrink the table: %%?line Mem = ets:info(T,memory), @@ -5169,7 +5181,7 @@ smp_unfix_fix_do() -> Left = NumOfObjs - Deleted, ?line Left = ets:info(T,size), ?line true = ets:info(T,fixed), - ?line Deleted = ets:info(T,kept_objects), + ?line Deleted = get_kept_objects(T), {Child, Mref} = spawn_opt(fun()-> ?line true = ets:info(T,fixed), @@ -5186,7 +5198,7 @@ smp_unfix_fix_do() -> end, Deleted), ?line 0 = ets:info(T,size), - ?line true = ets:info(T,kept_objects) >= Left, + ?line true = get_kept_objects(T) >= Left, ?line done = receive_any() end, [link, monitor, {scheduler,2}]), @@ -5199,7 +5211,7 @@ smp_unfix_fix_do() -> Child ! done, {'DOWN', Mref, process, Child, normal} = receive_any(), ?line false = ets:info(T,fixed), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), %%verify_table_load(T), ets:delete(T), process_flag(scheduler,0). @@ -5237,7 +5249,7 @@ otp_8166_do(WC) -> ZombieCrPid ! quit, {'DOWN', ZombieCrMref, process, ZombieCrPid, normal} = receive_any(), ?line false = ets:info(T,fixed), - ?line 0 = ets:info(T,kept_objects), + ?line 0 = get_kept_objects(T), %%verify_table_load(T), ets:delete(T), process_flag(scheduler,0). @@ -5304,7 +5316,7 @@ otp_8166_zombie_creator(T,Deleted) -> verify_table_load(T) -> ?line Stats = ets:info(T,stats), - ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen} = Stats, + ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats, ?line ok = if AvgLen > 7 -> io:format("Table overloaded: Stats=~p\n~p\n", @@ -5420,7 +5432,39 @@ types_do(Opts) -> ?line verify_etsmem(EtsMem). - +otp_9423(doc) -> ["vm-deadlock caused by race between ets:delete and others on write_concurrency table"]; +otp_9423(Config) when is_list(Config) -> + InitF = fun(_) -> {0,0} end, + ExecF = fun({S,F}) -> + receive + stop -> + io:format("~p got stop\n", [self()]), + [end_of_work | {"Succeded=",S,"Failed=",F}] + after 0 -> + %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]), + try ets:lookup(otp_9423, key) of + [] -> {S+1,F} + catch + error:badarg -> {S,F+1} + end + end + end, + FiniF = fun(R) -> R end, + case run_workers(InitF, ExecF, FiniF, infinite, 1) of + Pids when is_list(Pids) -> + %%[P ! start || P <- Pids], + repeat(fun() -> ets:new(otp_9423, [named_table, public, {write_concurrency,true}]), + ets:delete(otp_9423) + end, 10000), + [P ! stop || P <- Pids], + wait_pids(Pids), + ok; + + Skipped -> Skipped + end. + + + % % Utility functions: @@ -5434,21 +5478,30 @@ add_lists([E1|T1], [E2|T2], Acc) -> add_lists(T1, T2, [E1+E2 | Acc]). run_workers(InitF,ExecF,FiniF,Laps) -> + run_workers(InitF,ExecF,FiniF,Laps, 0). +run_workers(InitF,ExecF,FiniF,Laps, Exclude) -> case erlang:system_info(smp_support) of true -> - run_workers_do(InitF,ExecF,FiniF,Laps); + run_workers_do(InitF,ExecF,FiniF,Laps, Exclude); false -> {skipped,"No smp support"} end. - + run_workers_do(InitF,ExecF,FiniF,Laps) -> - NumOfProcs = erlang:system_info(schedulers), + run_workers_do(InitF,ExecF,FiniF,Laps, 0). +run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) -> + ?line NumOfProcs = case erlang:system_info(schedulers) of + N when (N > Exclude) -> N - Exclude + end, io:format("smp starting ~p workers\n",[NumOfProcs]), Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)], Parent = self(), Pids = [spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end) || Seed <- Seeds], - wait_pids(Pids). + case Laps of + infinite -> Pids; + _ -> wait_pids(Pids) + end. worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) -> io:format("smp worker ~p, seed=~p~n",[self(),Seed]), @@ -5463,6 +5516,8 @@ worker_loop(0, _, State) -> State; worker_loop(_, _, [end_of_work|State]) -> State; +worker_loop(infinite, ExecF, State) -> + worker_loop(infinite,ExecF,ExecF(State)); worker_loop(N, ExecF, State) -> worker_loop(N-1,ExecF,ExecF(State)). @@ -5517,20 +5572,21 @@ etsmem() -> case erlang:system_info({allocator,ets_alloc}) of false -> undefined; MemInfo -> - MSBCS = lists:foldl( - fun ({instance, _, L}, Acc) -> - {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L), - {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L), - [MBCS,SBCS | Acc] - end, - [], - MemInfo), + CS = lists:foldl( + fun ({instance, _, L}, Acc) -> + {value,{_,SBMBCS}} = lists:keysearch(sbmbcs, 1, L), + {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L), + {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L), + [SBMBCS,MBCS,SBCS | Acc] + end, + [], + MemInfo), lists:foldl( fun(L, {Bl0,BlSz0}) -> {value,{_,Bl,_,_}} = lists:keysearch(blocks, 1, L), {value,{_,BlSz,_,_}} = lists:keysearch(blocks_size, 1, L), {Bl0+Bl,BlSz0+BlSz} - end, {0,0}, MSBCS) + end, {0,0}, CS) end}, {Mem,AllTabs}. @@ -5872,7 +5928,7 @@ very_big_num(0, Result) -> ?line Result. make_port() -> - ?line open_port({spawn, efile}, [eof]). + ?line open_port({spawn, "efile"}, [eof]). make_pid() -> ?line spawn_link(?MODULE, sleeper, []). diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl index 80d4ea5fdc..74c08912be 100644 --- a/lib/stdlib/test/file_sorter_SUITE.erl +++ b/lib/stdlib/test/file_sorter_SUITE.erl @@ -89,7 +89,7 @@ basic(suite) -> basic(Config) when is_list(Config) -> Fmt = binary, Arg = {format,Fmt}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), P0 = pps(), ?line F1s = [F1] = to_files([[]], Fmt, Config), @@ -455,7 +455,7 @@ inout(suite) -> []; inout(Config) when is_list(Config) -> BTF = {format, binary_term}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is fun. End = fun(read) -> end_of_input end, @@ -522,7 +522,7 @@ many(doc) -> many(suite) -> []; many(Config) when is_list(Config) -> - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), PrivDir = ?privdir(Config), P0 = pps(), @@ -587,7 +587,7 @@ misc(suite) -> []; misc(Config) when is_list(Config) -> BTF = {format, binary_term}, - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), FFoo = filename:absname(Foo), P0 = pps(), @@ -704,7 +704,7 @@ misc(Config) when is_list(Config) -> sort(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,5} | XArgs]), TmpArgs = [{tmpdir,?privdir(Config)} | Args], - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is a fun. Output is a fun. ?line [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args), @@ -777,7 +777,7 @@ sort(Fmt, XArgs, Config) -> keysort(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]), TmpArgs = Args ++ [{tmpdir,?privdir(Config)}], - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is files. Output is a file. ?line ok = file_sorter:keysort(2, [], Foo, Args), @@ -836,7 +836,7 @@ keysort(Fmt, XArgs, Config) -> merge(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,5} | XArgs]), - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is a file. Output is a fun. ?line [] = file_sorter:merge([], output([], Fmt), Args), @@ -873,7 +873,7 @@ merge(Fmt, XArgs, Config) -> keymerge(Fmt, XArgs, Config) -> Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]), - Foo = outfile(foo, Config), + Foo = outfile("foo", Config), %% Input is files. Output is a file. ?line ok = file_sorter:keymerge(2, [], Foo, Args), diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl index a355097fe2..1de639a166 100644 --- a/lib/stdlib/test/filelib_SUITE.erl +++ b/lib/stdlib/test/filelib_SUITE.erl @@ -97,11 +97,12 @@ wildcard_errors(Config) when is_list(Config) -> wcc(Wc, Error) -> {'EXIT',{{badpattern,Error}, - [{filelib,compile_wildcard,1}|_]}} = (catch filelib:compile_wildcard(Wc)), + [{filelib,compile_wildcard,1,_}|_]}} = + (catch filelib:compile_wildcard(Wc)), {'EXIT',{{badpattern,Error}, - [{filelib,wildcard,1}|_]}} = (catch filelib:wildcard(Wc)), + [{filelib,wildcard,1,_}|_]}} = (catch filelib:wildcard(Wc)), {'EXIT',{{badpattern,Error}, - [{filelib,wildcard,2}|_]}} = (catch filelib:wildcard(Wc, ".")). + [{filelib,wildcard,2,_}|_]}} = (catch filelib:wildcard(Wc, ".")). do_wildcard_1(Dir, Wcf0) -> do_wildcard_2(Dir, Wcf0), @@ -243,7 +244,7 @@ otp_5960(doc) -> ["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"]; otp_5960(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), - ?line Dir = filename:join(PrivDir, otp_5960_dir), + ?line Dir = filename:join(PrivDir, "otp_5960_dir"), ?line Name1 = filename:join(Dir, name1), ?line Name2 = filename:join(Dir, name2), ?line ok = filelib:ensure_dir(Name1), % parent is created @@ -268,7 +269,7 @@ otp_5960(Config) when is_list(Config) -> ensure_dir_eexist(Config) when is_list(Config) -> ?line PrivDir = ?config(priv_dir, Config), - ?line Dir = filename:join(PrivDir, ensure_dir_eexist), + ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"), ?line Name = filename:join(Dir, "same_name_as_file_and_dir"), ?line ok = filelib:ensure_dir(Name), ?line ok = file:write_file(Name, <<"some string\n">>), diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl index 9e3e717e7d..b3a7edc140 100644 --- a/lib/stdlib/test/gen_event_SUITE.erl +++ b/lib/stdlib/test/gen_event_SUITE.erl @@ -25,13 +25,14 @@ -export([start/1, add_handler/1, add_sup_handler/1, delete_handler/1, swap_handler/1, swap_sup_handler/1, notify/1, sync_notify/1, call/1, info/1, hibernate/1, - call_format_status/1, error_format_status/1]). + call_format_status/1, call_format_status_anon/1, + error_format_status/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [start, {group, test_all}, hibernate, - call_format_status, error_format_status]. + call_format_status, call_format_status_anon, error_format_status]. groups() -> [{test_all, [], @@ -888,6 +889,22 @@ call_format_status(Config) when is_list(Config) -> ?line {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2, ok. +call_format_status_anon(suite) -> + []; +call_format_status_anon(doc) -> + ["Test that sys:get_status/1,2 calls format_status/2 for anonymous gen_event processes"]; +call_format_status_anon(Config) when is_list(Config) -> + ?line {ok, Pid} = gen_event:start(), + %% The 'Name' of the gen_event process will be a pid() here, so + %% the next line will crash if format_status can't string-ify pids. + ?line Status1 = sys:get_status(Pid), + ?line ok = gen_event:stop(Pid), + Header = "Status for event handler " ++ pid_to_list(Pid), + ?line {status, Pid, _, [_, _, Pid, [], Data1]} = Status1, + ?line Header = proplists:get_value(header, Data1), + ok. + + error_format_status(suite) -> []; error_format_status(doc) -> diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 54a98985cd..bb02a879c2 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -27,7 +27,7 @@ otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1, manpage/1, otp_6708/1, otp_7084/1, otp_7421/1, io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1, - io_fread_newlines/1, otp_8989/1]). + io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1]). %-define(debug, true). @@ -62,7 +62,7 @@ all() -> otp_6282, otp_6354, otp_6495, otp_6517, otp_6502, manpage, otp_6708, otp_7084, otp_7421, io_lib_collect_line_3_wb, cr_whitespace_in_string, - io_fread_newlines, otp_8989]. + io_fread_newlines, otp_8989, io_lib_fread_literal]. groups() -> []. @@ -1995,3 +1995,29 @@ otp_8989(Suite) when is_list(Suite) -> ?line "Hel " = fmt("~-4.*s", [3,Hello]), ?line "Hel " = fmt("~*.*s", [-4,3,Hello]), ok. + +io_lib_fread_literal(doc) -> + "OTP-9439 io_lib:fread bug for literate at end"; +io_lib_fread_literal(Suite) when is_list(Suite) -> + ?line {more,"~d",0,""} = io_lib:fread("~d", ""), + ?line {error,{fread,integer}} = io_lib:fread("~d", " "), + ?line {more,"~d",1,""} = io_lib:fread(" ~d", " "), + ?line {ok,[17],"X"} = io_lib:fread(" ~d", " 17X"), + %% + ?line {more,"d",0,""} = io_lib:fread("d", ""), + ?line {error,{fread,input}} = io_lib:fread("d", " "), + ?line {more,"d",1,""} = io_lib:fread(" d", " "), + ?line {ok,[],"X"} = io_lib:fread(" d", " dX"), + %% + ?line {done,eof,_} = io_lib:fread([], eof, "~d"), + ?line {done,eof,_} = io_lib:fread([], eof, " ~d"), + ?line {more,C1} = io_lib:fread([], " \n", " ~d"), + ?line {done,{error,{fread,input}},_} = io_lib:fread(C1, eof, " ~d"), + ?line {done,{ok,[18]},""} = io_lib:fread(C1, "18\n", " ~d"), + %% + ?line {done,eof,_} = io_lib:fread([], eof, "d"), + ?line {done,eof,_} = io_lib:fread([], eof, " d"), + ?line {more,C2} = io_lib:fread([], " \n", " d"), + ?line {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"), + ?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"), + ok. diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index 1565aa9bba..c95089117c 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -328,7 +328,7 @@ otp_6345(doc) -> ["'monitor' spawn_opt option"]; otp_6345(Config) when is_list(Config) -> Opts = [link,monitor], - {'EXIT', {badarg,[{proc_lib,check_for_monitor,_}|_Stack]}} = + {'EXIT', {badarg,[{proc_lib,check_for_monitor,_,_}|_Stack]}} = (catch proc_lib:start(?MODULE, otp_6345_init, [self()], 1000, Opts)), ok. diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl index c4817c0d38..3b2e637c84 100644 --- a/lib/stdlib/test/re_SUITE.erl +++ b/lib/stdlib/test/re_SUITE.erl @@ -454,115 +454,115 @@ error_handling(Config) when is_list(Config) -> % The malformed precomiled RE is detected after % the trap to re:grun from grun, in the grun function clause % that handles precompiled expressions - ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:run("apa",{1,2,3,4},[global])), % An invalid capture list will also cause a badarg late, % but with a non pre compiled RE, the exception should be thrown by the % grun function clause that handles RE's compiled implicitly by % the run/3 BIF before trapping. - ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:run("apa","p",[{capture,[1,{a}]},global])), % And so the case of a precompiled expression together with % a compile-option (binary and list subject): ?line {ok,RE} = re:compile("(p)"), ?line {match,[[{1,1},{1,1}]]} = re:run(<<"apa">>,RE,[global]), ?line {match,[[{1,1},{1,1}]]} = re:run("apa",RE,[global]), - {'EXIT',{badarg,[{re,run, - [<<"apa">>, - {re_pattern,1,0,_}, - [global,unicode]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,run, + [<<"apa">>, + {re_pattern,1,0,_}, + [global,unicode]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:run(<<"apa">>,RE,[global,unicode])), - {'EXIT',{badarg,[{re,run, - ["apa", - {re_pattern,1,0,_}, - [global,unicode]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,run, + ["apa", + {re_pattern,1,0,_}, + [global,unicode]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:run("apa",RE,[global,unicode])), ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])), ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])), % The replace errors: - ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:replace("apa",{1,2,3,4},"X",[])), - ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:replace("apa",{1,2,3,4},"X",[global])), ?line {'EXIT',{badarg,[{re,replace, ["apa", {re_pattern,1,0,_}, "X", - [unicode]]}, - {?MODULE, error_handling,1} | _]}} = + [unicode]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:replace("apa",RE,"X",[unicode])), ?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])), ?line {'EXIT',{badarg,[{re,replace, - ["apa","p","X",[{capture,all,binary}]]}, - {?MODULE, error_handling,1} | _]}} = + ["apa","p","X",[{capture,all,binary}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{capture,all,binary}]))), ?line {'EXIT',{badarg,[{re,replace, - ["apa","p","X",[{capture,all}]]}, - {?MODULE, error_handling,1} | _]}} = + ["apa","p","X",[{capture,all}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{capture,all}]))), ?line {'EXIT',{badarg,[{re,replace, - ["apa","p","X",[{return,banana}]]}, - {?MODULE, error_handling,1} | _]}} = + ["apa","p","X",[{return,banana}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{return,banana}]))), ?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])), % Badarg, not compile error. ?line {'EXIT',{badarg,[{re,replace, - ["apa","(p","X",[{return,banana}]]}, - {?MODULE, error_handling,1} | _]}} = + ["apa","(p","X",[{return,banana}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch iolist_to_binary(re:replace("apa","(p","X", [{return,banana}]))), % And the split errors: ?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])), ?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])), - ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa","p",[global])), - ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa","p",[{capture,all}])), - ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_}, + {?MODULE, error_handling,1,_} | _]}} = (catch re:split("apa","p",[{capture,all,binary}])), - ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa",{1,2,3,4})), - ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]}, - {?MODULE, error_handling,1} | _]}} = + ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa",{1,2,3,4},[])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, - [unicode]]}, - {?MODULE, error_handling,1} | _]}} = + [unicode]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa",RE,[unicode])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, - [{return,banana}]]}, - {?MODULE, error_handling,1} | _]}} = + [{return,banana}]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa",RE,[{return,banana}])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, - [banana]]}, - {?MODULE, error_handling,1} | _]}} = + [banana]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa",RE,[banana])), ?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")), %Exception on bad argument, not compilation error ?line {'EXIT',{badarg,[{re,split, ["apa", "(p", - [banana]]}, - {?MODULE, error_handling,1} | _]}} = + [banana]],_}, + {?MODULE,error_handling,1,_} | _]}} = (catch re:split("apa","(p",[banana])), ?t:timetrap_cancel(Dog), ok. diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index 8273377ba1..b6019b86f0 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -2388,12 +2388,12 @@ otp_6554(Config) when is_list(Config) -> comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>), ?line "exception error: no function clause matching" = comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>), - ?line "exception error: {function_clause,[{erl_eval,do_apply,[unproper|list]}"++_ = + ?line "exception error: {function_clause," = comm_err(<<"erlang:error(function_clause, [unproper | list]).">>), ?line "exception error: function_clause" = comm_err(<<"erlang:error(function_clause, 4).">>), %% Cheating: - ?line "exception error: no function clause matching erl_eval:do_apply(4)" = + ?line "exception error: no function clause matching erl_eval:do_apply(4)" ++ _ = comm_err(<<"erlang:error(function_clause, [4]).">>), ?line "exception error: no function clause matching" ++ _ = comm_err(<<"fun(a, b, c, d) -> foo end" @@ -2406,7 +2406,7 @@ otp_6554(Config) when is_list(Config) -> comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>), ?line "exception error: no function clause matching lists:reverse(" ++ _ = comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>), - ?line "exception error: no function clause matching lists:reverse(34)" = + ?line "exception error: no function clause matching lists:reverse(34) (lists.erl, line " ++ _ = comm_err(<<"lists:reverse(34).">>), ?line "exception error: no true branch found when evaluating an if expression" = comm_err(<<"if length([a,b]) > 17 -> a end.">>), diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl index 01de1f0600..73b282149a 100644 --- a/lib/stdlib/test/sofs_SUITE.erl +++ b/lib/stdlib/test/sofs_SUITE.erl @@ -1602,19 +1602,15 @@ relative_product_2(Conf) when is_list(Conf) -> from_term([{{a},b}])}, ER)), ?line {'EXIT', {badarg, _}} = (catch relative_product({}, ER)), - ?line eval(relative_product({relation([{a,b}])}, - from_term([],[{{atom},atom}])), - ER), - ?line eval(relative_product({relation([{a,b}]),relation([{a,1}])}, - from_term([{{b,1},{tjo,hej,sa}}])), - from_term([{a,{tjo,hej,sa}}])), - ?line eval(relative_product({relation([{a,b}]), ER}, - from_term([{{a,b},b}])), - ER), - ?line eval(relative_product({relation([{a,b},{c,a}]), - relation([{a,1},{a,2}])}, - from_term([{{b,1},b1},{{b,2},b2}])), - relation([{a,b1},{a,b2}])), + ?line relprod2({relation([{a,b}])}, from_term([],[{{atom},atom}]), ER), + ?line relprod2({relation([{a,b}]),relation([{a,1}])}, + from_term([{{b,1},{tjo,hej,sa}}]), + from_term([{a,{tjo,hej,sa}}])), + ?line relprod2({relation([{a,b}]), ER}, from_term([{{a,b},b}]), ER), + ?line relprod2({relation([{a,b},{c,a}]), + relation([{a,1},{a,2}])}, + from_term([{{b,1},b1},{{b,2},b2}]), + relation([{a,b1},{a,b2}])), ?line eval(relative_product({relation([{a,b}]), ER}), from_term([],[{atom,{atom,atom}}])), ?line eval(relative_product({from_term([{{a,[a,b]},[a]}]), @@ -1622,6 +1618,11 @@ relative_product_2(Conf) when is_list(Conf) -> from_term([{{a,[a,b]},{[a],[[a,b]]}}])), ok. +relprod2(A1T, A2, R) -> + %% A tuple as first argument is the old interface: + eval(relative_product(A1T, A2), R), + eval(relative_product(tuple_to_list(A1T), A2), R). + product_1(suite) -> []; product_1(doc) -> [""]; product_1(Conf) when is_list(Conf) -> @@ -1878,11 +1879,11 @@ digraph(Conf) when is_list(Conf) -> ?line {'EXIT', {badarg, _}} = (catch family_to_digraph(set([a]))), - ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} = + ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} = (catch family_to_digraph(set([a]), [foo])), - ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} = + ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} = (catch family_to_digraph(F, [foo])), - ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_]}|_]}} = + ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} = (catch family_to_digraph(family([{a,[a]}]),[acyclic])), ?line G1 = family_to_digraph(E), diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl index 1dcd4be21e..6969c095a0 100644 --- a/lib/stdlib/test/string_SUITE.erl +++ b/lib/stdlib/test/string_SUITE.erl @@ -273,9 +273,9 @@ words(Config) when is_list(Config) -> ?line 2 = string:words("2.35", $.), ?line 100 = string:words(string:copies(". ", 100)), %% invalid arg type - ?line {'EXIT',_} = (catch string:chars(hej)), + ?line {'EXIT',_} = (catch string:chars(hej, 1)), %% invalid arg type - ?line {'EXIT',_} = (catch string:chars("hej", " ")), + ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")), ok. diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl index 3198be0fed..f819594c46 100644 --- a/lib/stdlib/test/supervisor_1.erl +++ b/lib/stdlib/test/supervisor_1.erl @@ -62,6 +62,12 @@ handle_info(die, State) -> handle_info(stop, State) -> {stop, normal, State}; +handle_info({'EXIT',_,shutdown}, State) -> + {stop, shutdown, State}; + +handle_info({'EXIT',_,{shutdown,Term}}, State) -> + {stop, {shutdown,Term}, State}; + handle_info({sleep, Time}, State) -> io:format("FOO: ~p~n", [Time]), timer:sleep(Time), diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 6e927da2ab..2aa3131aeb 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -20,45 +20,50 @@ -module(supervisor_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). +-define(TIMEOUT, 1000). %% Testserver specific export -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). -%% Indirect spawn export --export([init/1]). +%% Internal export +-export([init/1, terminate_all_children/1]). %% API tests -export([ sup_start_normal/1, sup_start_ignore_init/1, - sup_start_ignore_child/1, sup_start_error_return/1, - sup_start_fail/1, sup_stop_infinity/1, - sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1, - child_adm_simple/1, child_specs/1, extra_return/1]). + sup_start_ignore_child/1, sup_start_error_return/1, + sup_start_fail/1, sup_stop_infinity/1, + sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1, + child_adm_simple/1, child_specs/1, extra_return/1]). %% Tests concept permanent, transient and temporary -export([ permanent_normal/1, transient_normal/1, - temporary_normal/1, - permanent_abnormal/1, transient_abnormal/1, - temporary_abnormal/1]). + temporary_normal/1, + permanent_shutdown/1, transient_shutdown/1, + temporary_shutdown/1, + permanent_abnormal/1, transient_abnormal/1, + temporary_abnormal/1, temporary_bystander/1]). %% Restart strategy tests -export([ one_for_one/1, - one_for_one_escalation/1, one_for_all/1, - one_for_all_escalation/1, - simple_one_for_one/1, simple_one_for_one_escalation/1, - rest_for_one/1, rest_for_one_escalation/1, - simple_one_for_one_extra/1]). + one_for_one_escalation/1, one_for_all/1, + one_for_all_escalation/1, + simple_one_for_one/1, simple_one_for_one_escalation/1, + rest_for_one/1, rest_for_one_escalation/1, + simple_one_for_one_extra/1]). %% Misc tests -export([child_unlink/1, tree/1, count_children_memory/1, - do_not_save_start_parameters_for_temporary_children/1]). + do_not_save_start_parameters_for_temporary_children/1, + do_not_save_child_specs_for_temporary_children/1, + simple_one_for_one_scale_many_temporary_children/1]). -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}]. all() -> [{group, sup_start}, {group, sup_stop}, child_adm, @@ -68,8 +73,11 @@ all() -> {group, restart_simple_one_for_one}, {group, restart_rest_for_one}, {group, normal_termination}, + {group, shutdown_termination}, {group, abnormal_termination}, child_unlink, tree, - count_children_memory, do_not_save_start_parameters_for_temporary_children]. + count_children_memory, do_not_save_start_parameters_for_temporary_children, + do_not_save_child_specs_for_temporary_children, + simple_one_for_one_scale_many_temporary_children, temporary_bystander]. groups() -> [{sup_start, [], @@ -81,6 +89,8 @@ groups() -> sup_stop_brutal_kill]}, {normal_termination, [], [permanent_normal, transient_normal, temporary_normal]}, + {shutdown_termination, [], + [permanent_shutdown, transient_shutdown, temporary_shutdown]}, {abnormal_termination, [], [permanent_abnormal, transient_abnormal, temporary_abnormal]}, @@ -94,8 +104,10 @@ groups() -> {restart_rest_for_one, [], [rest_for_one, rest_for_one_escalation]}]. -init_per_suite(Config) -> - Config. +init_per_suite(Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = test_server:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. end_per_suite(_Config) -> ok. @@ -107,19 +119,19 @@ end_per_group(_GroupName, Config) -> Config. init_per_testcase(count_children_memory, Config) -> - MemoryState = erlang:system_info(allocator), - case count_children_allocator_test(MemoryState) of - true -> Config; - false -> + try erlang:memory() of + _ -> Config + catch error:notsup -> {skip, "+Meamin used during test; erlang:memory/1 not available"} end; init_per_testcase(_Case, Config) -> + erlang:display(_Case), Config. end_per_testcase(_Case, _Config) -> ok. -start(InitResult) -> +start_link(InitResult) -> supervisor:start_link({local, sup_test}, ?MODULE, InitResult). %% Simulate different supervisors callback. @@ -136,145 +148,87 @@ get_child_counts(Supervisor) -> proplists:get_value(supervisors, Counts), proplists:get_value(workers, Counts)]. -%------------------------------------------------------------------------- -% Test cases starts here. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- +%% Test cases starts here. +%%------------------------------------------------------------------------- sup_start_normal(doc) -> ["Tests that the supervisor process starts correctly and that it " - "can be terminated gracefully."]; + "can be terminated gracefully."]; sup_start_normal(suite) -> []; sup_start_normal(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), - ?line exit(Pid, shutdown), - receive - {'EXIT', Pid, shutdown} -> - ok; - {'EXIT', Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 2000 -> - ?line test_server:fail(no_exit_reason) - end, - ok. -%------------------------------------------------------------------------- + {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + terminate(Pid, shutdown). + +%%------------------------------------------------------------------------- sup_start_ignore_init(doc) -> ["Tests what happens if init-callback returns ignore"]; sup_start_ignore_init(suite) -> []; sup_start_ignore_init(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line ignore = start(ignore), - - receive - {'EXIT', _Pid, normal} -> - ok; - {'EXIT', _Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 2000 -> - ?line test_server:fail(no_exit_reason) - end, - ok. + ignore = start_link(ignore), + check_exit_reason(normal). - -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_start_ignore_child(doc) -> ["Tests what happens if init-callback returns ignore"]; sup_start_ignore_child(suite) -> []; sup_start_ignore_child(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, [ignore]}, permanent, 1000, worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - - ?line {ok, undefined} = supervisor:start_child(sup_test, Child1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), - ?line [{child2, CPid2, worker, []},{child1, undefined, worker, []}] - = supervisor:which_children(sup_test), - ?line [2,1,0,2] = get_child_counts(sup_test), + {ok, undefined} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), - ok. + [{child2, CPid2, worker, []},{child1, undefined, worker, []}] + = supervisor:which_children(sup_test), + [2,1,0,2] = get_child_counts(sup_test). -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_start_error_return(doc) -> ["Tests what happens if init-callback returns a invalid value"]; sup_start_error_return(suite) -> []; sup_start_error_return(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {error, Term} = start(invalid), + {error, Term} = start_link(invalid), + check_exit_reason(Term). - receive - {'EXIT', _Pid, Term} -> - ok; - {'EXIT', _Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 2000 -> - ?line test_server:fail(no_exit_reason) - end, - ok. - -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_start_fail(doc) -> ["Tests what happens if init-callback fails"]; sup_start_fail(suite) -> []; sup_start_fail(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {error, Term} = start(fail), + {error, Term} = start_link(fail), + check_exit_reason(Term). - receive - {'EXIT', _Pid, Term} -> - ok; - {'EXIT', _Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 2000 -> - ?line test_server:fail(no_exit_reason) - end, - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_stop_infinity(doc) -> ["See sup_stop/1 when Shutdown = infinity, this walue is only allowed " - "for children of type supervisor"]; + "for children of type supervisor"]; sup_stop_infinity(suite) -> []; sup_stop_infinity(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, permanent, infinity, supervisor, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, - infinity, worker, []}, - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), + infinity, worker, []}, + {ok, CPid1} = supervisor:start_child(sup_test, Child1), link(CPid1), - ?line {error, {invalid_shutdown,infinity}} = - supervisor:start_child(sup_test, Child2), + {error, {invalid_shutdown,infinity}} = + supervisor:start_child(sup_test, Child2), - ?line exit(Pid, shutdown), + terminate(Pid, shutdown), + check_exit_reason(CPid1, shutdown). - receive - {'EXIT', Pid, shutdown} -> - ok; - {'EXIT', Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 5000 -> - ?line test_server:fail(no_exit_reason) - end, - receive - {'EXIT', CPid1, shutdown} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - after - 2000 -> ?line test_server:fail(no_exit_reason) - end, - ok. - -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_stop_timeout(doc) -> ["See sup_stop/1 when Shutdown = 1000"]; @@ -282,93 +236,47 @@ sup_stop_timeout(suite) -> []; sup_stop_timeout(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - + CPid2 ! {sleep, 200000}, - ?line exit(Pid, shutdown), + terminate(Pid, shutdown), - receive - {'EXIT', Pid, shutdown} -> - ok; - {'EXIT', Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 5000 -> - ?line test_server:fail(no_exit_reason) - end, + check_exit_reason(CPid1, shutdown), + check_exit_reason(CPid2, killed). - receive - {'EXIT', CPid1, shutdown} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason,Reason}) - after - 2000 -> ?line test_server:fail(no_exit_reason) - end, - - receive - {'EXIT', CPid2, killed} -> ok; - {'EXIT', CPid2, Reason2} -> - ?line test_server:fail({bad_exit_reason, Reason2}) - after - 2000 -> ?line test_server:fail(no_exit_reason) - end, - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- sup_stop_brutal_kill(doc) -> ["See sup_stop/1 when Shutdown = brutal_kill"]; sup_stop_brutal_kill(suite) -> []; sup_stop_brutal_kill(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, brutal_kill, worker, []}, - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - ?line exit(Pid, shutdown), + terminate(Pid, shutdown), - receive - {'EXIT', Pid, shutdown} -> - ok; - {'EXIT', Pid, Else} -> - ?line test_server:fail({bad_exit_reason, Else}) - after - 5000 -> - ?line test_server:fail(no_exit_reason) - end, + check_exit_reason(CPid1, shutdown), + check_exit_reason(CPid2, killed). - receive - {'EXIT', CPid1, shutdown} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - after - 2000 -> ?line test_server:fail(no_exit_reason) - end, - receive - {'EXIT', CPid2, killed} -> ok; - {'EXIT', CPid2, Reason2} -> - ?line test_server:fail({bad_exit_reason, Reason2}) - after - 2000 -> ?line test_server:fail(no_exit_reason) - end, - ok. - -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- extra_return(doc) -> ["The start function provided to start a child may " "return {ok, Pid} or {ok, Pid, Info}, if it returns " @@ -382,46 +290,40 @@ extra_return(Config) when is_list(Config) -> Child = {child1, {supervisor_1, start_child, [extra_return]}, permanent, 1000, worker, []}, - ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, [Child]}}), - ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child]}}), + [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), link(CPid), - ?line {error, not_found} = supervisor:terminate_child(sup_test, hej), - ?line {error, not_found} = supervisor:delete_child(sup_test, hej), - ?line {error, not_found} = supervisor:restart_child(sup_test, hej), - ?line {error, running} = supervisor:delete_child(sup_test, child1), - ?line {error, running} = supervisor:restart_child(sup_test, child1), - ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), - - ?line ok = supervisor:terminate_child(sup_test, child1), - receive - {'EXIT', CPid, shutdown} -> ok; - {'EXIT', CPid, Reason} -> - ?line test_server:fail({bad_reason, Reason}) - after 1000 -> - ?line test_server:fail(no_child_termination) - end, - ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), - ?line [1,0,0,1] = get_child_counts(sup_test), - - ?line {ok, CPid2,extra_return} = + {error, not_found} = supervisor:terminate_child(sup_test, hej), + {error, not_found} = supervisor:delete_child(sup_test, hej), + {error, not_found} = supervisor:restart_child(sup_test, hej), + {error, running} = supervisor:delete_child(sup_test, child1), + {error, running} = supervisor:restart_child(sup_test, child1), + [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + + ok = supervisor:terminate_child(sup_test, child1), + check_exit_reason(CPid, shutdown), + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test), + + {ok, CPid2,extra_return} = supervisor:restart_child(sup_test, child1), - ?line [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), + [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), - ?line ok = supervisor:terminate_child(sup_test, child1), - ?line ok = supervisor:terminate_child(sup_test, child1), - ?line ok = supervisor:delete_child(sup_test, child1), - ?line {error, not_found} = supervisor:restart_child(sup_test, child1), - ?line [] = supervisor:which_children(sup_test), - ?line [0,0,0,0] = get_child_counts(sup_test), + ok = supervisor:terminate_child(sup_test, child1), + ok = supervisor:terminate_child(sup_test, child1), + ok = supervisor:delete_child(sup_test, child1), + {error, not_found} = supervisor:restart_child(sup_test, child1), + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test), - ?line {ok, CPid3, extra_return} = supervisor:start_child(sup_test, Child), - ?line [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), + {ok, CPid3, extra_return} = supervisor:start_child(sup_test, Child), + [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- child_adm(doc)-> ["Test API functions start_child/2, terminate_child/2, delete_child/2 " "restart_child/2, which_children/1, count_children/1. Only correct " @@ -432,116 +334,124 @@ child_adm(Config) when is_list(Config) -> process_flag(trap_exit, true), Child = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, [Child]}}), - ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child]}}), + [{child1, CPid, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), link(CPid), %% Start of an already runnig process - ?line {error,{already_started, CPid}} = + {error,{already_started, CPid}} = supervisor:start_child(sup_test, Child), - + %% Termination - ?line {error, not_found} = supervisor:terminate_child(sup_test, hej), - ?line {'EXIT',{noproc,{gen_server,call, _}}} = + {error, not_found} = supervisor:terminate_child(sup_test, hej), + {'EXIT',{noproc,{gen_server,call, _}}} = (catch supervisor:terminate_child(foo, child1)), - ?line ok = supervisor:terminate_child(sup_test, child1), - receive - {'EXIT', CPid, shutdown} -> ok; - {'EXIT', CPid, Reason} -> - ?line test_server:fail({bad_reason, Reason}) - after 1000 -> - ?line test_server:fail(no_child_termination) - end, - ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), - ?line [1,0,0,1] = get_child_counts(sup_test), + ok = supervisor:terminate_child(sup_test, child1), + check_exit_reason(CPid, shutdown), + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test), %% Like deleting something that does not exist, it will succeed! - ?line ok = supervisor:terminate_child(sup_test, child1), + ok = supervisor:terminate_child(sup_test, child1), %% Start of already existing but not running process - ?line {error,already_present} = - supervisor:start_child(sup_test, Child), + {error,already_present} = supervisor:start_child(sup_test, Child), %% Restart - ?line {ok, CPid2} = supervisor:restart_child(sup_test, child1), - ?line [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), - ?line {error, running} = supervisor:restart_child(sup_test, child1), - ?line {error, not_found} = supervisor:restart_child(sup_test, child2), - + {ok, CPid2} = supervisor:restart_child(sup_test, child1), + [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + {error, running} = supervisor:restart_child(sup_test, child1), + {error, not_found} = supervisor:restart_child(sup_test, child2), + %% Deletion - ?line {error, running} = supervisor:delete_child(sup_test, child1), - ?line {error, not_found} = supervisor:delete_child(sup_test, hej), - ?line {'EXIT',{noproc,{gen_server,call, _}}} = + {error, running} = supervisor:delete_child(sup_test, child1), + {error, not_found} = supervisor:delete_child(sup_test, hej), + {'EXIT',{noproc,{gen_server,call, _}}} = (catch supervisor:delete_child(foo, child1)), - ?line ok = supervisor:terminate_child(sup_test, child1), - ?line ok = supervisor:delete_child(sup_test, child1), - ?line {error, not_found} = supervisor:restart_child(sup_test, child1), - ?line [] = supervisor:which_children(sup_test), - ?line [0,0,0,0] = get_child_counts(sup_test), - + ok = supervisor:terminate_child(sup_test, child1), + ok = supervisor:delete_child(sup_test, child1), + {error, not_found} = supervisor:restart_child(sup_test, child1), + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test), + %% Start - ?line {'EXIT',{noproc,{gen_server,call, _}}} = + {'EXIT',{noproc,{gen_server,call, _}}} = (catch supervisor:start_child(foo, Child)), - ?line {ok, CPid3} = supervisor:start_child(sup_test, Child), - ?line [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), + {ok, CPid3} = supervisor:start_child(sup_test, Child), + [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), - ?line {'EXIT',{noproc,{gen_server,call,[foo,which_children,infinity]}}} + %% Terminate with Pid not allowed when not simple_one_for_one + {error,not_found} = supervisor:terminate_child(sup_test, CPid3), + [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + + {'EXIT',{noproc,{gen_server,call,[foo,which_children,infinity]}}} = (catch supervisor:which_children(foo)), - ?line {'EXIT',{noproc,{gen_server,call,[foo,count_children,infinity]}}} + {'EXIT',{noproc,{gen_server,call,[foo,count_children,infinity]}}} = (catch supervisor:count_children(foo)), ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- child_adm_simple(doc) -> ["The API functions terminate_child/2, delete_child/2 " "restart_child/2 are not valid for a simple_one_for_one supervisor " - "check that the correct error message is returned."]; + "check that the correct error message is returned."]; child_adm_simple(suite) -> []; child_adm_simple(Config) when is_list(Config) -> Child = {child, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, _Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), %% In simple_one_for_one all children are added dynamically - ?line [] = supervisor:which_children(sup_test), - ?line [1,0,0,0] = get_child_counts(sup_test), - + [] = supervisor:which_children(sup_test), + [1,0,0,0] = get_child_counts(sup_test), + %% Start - ?line {'EXIT',{noproc,{gen_server,call, _}}} = + {'EXIT',{noproc,{gen_server,call, _}}} = (catch supervisor:start_child(foo, [])), - ?line {ok, CPid1} = supervisor:start_child(sup_test, []), - ?line [{undefined, CPid1, worker, []}] = + {ok, CPid1} = supervisor:start_child(sup_test, []), + [{undefined, CPid1, worker, []}] = supervisor:which_children(sup_test), - ?line [1,1,0,1] = get_child_counts(sup_test), - - ?line {ok, CPid2} = supervisor:start_child(sup_test, []), - ?line Children = supervisor:which_children(sup_test), - ?line 2 = length(Children), - ?line true = lists:member({undefined, CPid2, worker, []}, Children), - ?line true = lists:member({undefined, CPid1, worker, []}, Children), - ?line [1,2,0,2] = get_child_counts(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + + {ok, CPid2} = supervisor:start_child(sup_test, []), + Children = supervisor:which_children(sup_test), + 2 = length(Children), + true = lists:member({undefined, CPid2, worker, []}, Children), + true = lists:member({undefined, CPid1, worker, []}, Children), + [1,2,0,2] = get_child_counts(sup_test), %% Termination - ?line {error, simple_one_for_one} = - supervisor:terminate_child(sup_test, child1), + {error, simple_one_for_one} = supervisor:terminate_child(sup_test, child1), + [1,2,0,2] = get_child_counts(sup_test), + ok = supervisor:terminate_child(sup_test,CPid1), + [_] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + false = erlang:is_process_alive(CPid1), + %% Terminate non-existing proccess is ok + ok = supervisor:terminate_child(sup_test,CPid1), + [_] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test), + %% Terminate pid which is not a child of this supervisor is not ok + NoChildPid = spawn_link(fun() -> receive after infinity -> ok end end), + {error, not_found} = supervisor:terminate_child(sup_test, NoChildPid), + true = erlang:is_process_alive(NoChildPid), %% Restart - ?line {error, simple_one_for_one} = - supervisor:restart_child(sup_test, child1), - + {error, simple_one_for_one} = supervisor:restart_child(sup_test, child1), + %% Deletion - ?line {error, simple_one_for_one} = - supervisor:delete_child(sup_test, child1), + {error, simple_one_for_one} = supervisor:delete_child(sup_test, child1), ok. - -%------------------------------------------------------------------------- + +%%------------------------------------------------------------------------- child_specs(doc) -> ["Tests child specs, invalid formats should be rejected."]; child_specs(suite) -> []; child_specs(Config) when is_list(Config) -> process_flag(trap_exit, true), - ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), - ?line {error, _} = supervisor:start_child(sup_test, hej), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + {error, _} = supervisor:start_child(sup_test, hej), %% Bad child specs B1 = {child, mfa, permanent, 1000, worker, []}, @@ -551,7 +461,7 @@ child_specs(Config) when is_list(Config) -> B5 = {child, {m,f,[a]}, permanent, infinity, worker, []}, B6 = {child, {m,f,[a]}, permanent, 1000, worker, dy}, B7 = {child, {m,f,[a]}, permanent, 1000, worker, [1,2,3]}, - + %% Correct child specs! %% <Modules> (last parameter in a child spec) can be [] as we do %% not test code upgrade here. @@ -560,327 +470,373 @@ child_specs(Config) when is_list(Config) -> C3 = {child, {m,f,[a]}, temporary, 1000, worker, dynamic}, C4 = {child, {m,f,[a]}, transient, 1000, worker, [m]}, - ?line {error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1), - ?line {error, {invalid_restart_type, prmanent}} = + {error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1), + {error, {invalid_restart_type, prmanent}} = supervisor:start_child(sup_test, B2), - ?line {error, {invalid_shutdown,-10}} - = supervisor:start_child(sup_test, B3), - ?line {error, {invalid_child_type,wrker}} + {error, {invalid_shutdown,-10}} + = supervisor:start_child(sup_test, B3), + {error, {invalid_child_type,wrker}} = supervisor:start_child(sup_test, B4), - ?line {error, _} = supervisor:start_child(sup_test, B5), - ?line {error, {invalid_modules,dy}} + {error, _} = supervisor:start_child(sup_test, B5), + {error, {invalid_modules,dy}} = supervisor:start_child(sup_test, B6), - - ?line {error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]), - ?line {error, {invalid_restart_type,prmanent}} = + + {error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]), + {error, {invalid_restart_type,prmanent}} = supervisor:check_childspecs([B2]), - ?line {error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]), - ?line {error, {invalid_child_type,wrker}} + {error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]), + {error, {invalid_child_type,wrker}} = supervisor:check_childspecs([B4]), - ?line {error, _} = supervisor:check_childspecs([B5]), - ?line {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]), - ?line {error, {invalid_module, 1}} = + {error, _} = supervisor:check_childspecs([B5]), + {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]), + {error, {invalid_module, 1}} = supervisor:check_childspecs([B7]), - ?line ok = supervisor:check_childspecs([C1]), - ?line ok = supervisor:check_childspecs([C2]), - ?line ok = supervisor:check_childspecs([C3]), - ?line ok = supervisor:check_childspecs([C4]), + ok = supervisor:check_childspecs([C1]), + ok = supervisor:check_childspecs([C2]), + ok = supervisor:check_childspecs([C3]), + ok = supervisor:check_childspecs([C4]), ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- permanent_normal(doc) -> ["A permanent child should always be restarted"]; permanent_normal(suite) -> []; permanent_normal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! stop, - test_server:sleep(100), - ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid1, child1, normal), + + [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), case is_pid(Pid) of true -> ok; false -> - ?line test_server:fail({permanent_child_not_restarted, Child1}) + test_server:fail({permanent_child_not_restarted, Child1}) end, - ?line [1,1,0,1] = get_child_counts(sup_test), + [1,1,0,1] = get_child_counts(sup_test). - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- transient_normal(doc) -> ["A transient child should not be restarted if it exits with " "reason normal"]; transient_normal(suite) -> []; transient_normal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! stop, - test_server:sleep(100), - - ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), - ?line [1,0,0,1] = get_child_counts(sup_test), - ok. -%------------------------------------------------------------------------- + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid1, child1, normal), + + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- temporary_normal(doc) -> ["A temporary process should never be restarted"]; temporary_normal(suite) -> []; temporary_normal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! stop, - test_server:sleep(100), - - ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), - ?line [1,0,0,1] = get_child_counts(sup_test), - ok. + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid1, child1, normal), + + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +permanent_shutdown(doc) -> + ["A permanent child should always be restarted"]; +permanent_shutdown(suite) -> []; +permanent_shutdown(Config) when is_list(Config) -> + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, + worker, []}, + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), -%------------------------------------------------------------------------- + terminate(SupPid, CPid1, child1, shutdown), + + [{child1, CPid2 ,worker,[]}] = supervisor:which_children(sup_test), + case is_pid(CPid2) of + true -> + ok; + false -> + test_server:fail({permanent_child_not_restarted, Child1}) + end, + [1,1,0,1] = get_child_counts(sup_test), + + terminate(SupPid, CPid2, child1, {shutdown, some_info}), + + [{child1, CPid3 ,worker,[]}] = supervisor:which_children(sup_test), + case is_pid(CPid3) of + true -> + ok; + false -> + test_server:fail({permanent_child_not_restarted, Child1}) + end, + + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +transient_shutdown(doc) -> + ["A transient child should not be restarted if it exits with " + "reason shutdown or {shutdown,Term}"]; +transient_shutdown(suite) -> []; +transient_shutdown(Config) when is_list(Config) -> + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000, + worker, []}, + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid1, child1, shutdown), + + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test), + + {ok, CPid2} = supervisor:restart_child(sup_test, child1), + + terminate(SupPid, CPid2, child1, {shutdown, some_info}), + + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +temporary_shutdown(doc) -> + ["A temporary process should never be restarted"]; +temporary_shutdown(suite) -> []; +temporary_shutdown(Config) when is_list(Config) -> + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000, + worker, []}, + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid1, child1, shutdown), + + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test), + + {ok, CPid2} = supervisor:start_child(sup_test, Child1), + + terminate(SupPid, CPid2, child1, {shutdown, some_info}), + + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- permanent_abnormal(doc) -> ["A permanent child should always be restarted"]; permanent_abnormal(suite) -> []; permanent_abnormal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! die, - test_server:sleep(100), - ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + terminate(SupPid, CPid1, child1, abnormal), + + [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), case is_pid(Pid) of true -> ok; false -> - ?line test_server:fail({permanent_child_not_restarted, Child1}) + test_server:fail({permanent_child_not_restarted, Child1}) end, - ?line [1,1,0,1] = get_child_counts(sup_test), + [1,1,0,1] = get_child_counts(sup_test). - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- transient_abnormal(doc) -> ["A transient child should be restarted if it exits with " "reason abnormal"]; transient_abnormal(suite) -> []; transient_abnormal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! die, - test_server:sleep(100), - - ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + terminate(SupPid, CPid1, child1, abnormal), + + [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test), case is_pid(Pid) of true -> ok; false -> - ?line test_server:fail({transient_child_not_restarted, Child1}) + test_server:fail({transient_child_not_restarted, Child1}) end, - ?line [1,1,0,1] = get_child_counts(sup_test), + [1,1,0,1] = get_child_counts(sup_test). - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- temporary_abnormal(doc) -> ["A temporary process should never be restarted"]; temporary_abnormal(suite) -> []; temporary_abnormal(Config) when is_list(Config) -> - ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000, worker, []}, - - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - - CPid1 ! die, - test_server:sleep(100), - - ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), - ?line [1,0,0,1] = get_child_counts(sup_test), - ok. -%------------------------------------------------------------------------- + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + terminate(SupPid, CPid1, child1, abnormal), + + [] = supervisor:which_children(sup_test), + [0,0,0,0] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +temporary_bystander(doc) -> + ["A temporary process killed as part of a rest_for_one or one_for_all " + "restart strategy should not be restarted given its args are not " + " saved. Otherwise the supervisor hits its limit and crashes."]; +temporary_bystander(suite) -> []; +temporary_bystander(_Config) -> + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 100, + worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, 100, + worker, []}, + {ok, SupPid1} = supervisor:start_link(?MODULE, {ok, {{one_for_all, 2, 300}, []}}), + {ok, SupPid2} = supervisor:start_link(?MODULE, {ok, {{rest_for_one, 2, 300}, []}}), + unlink(SupPid1), % otherwise we crash with it + unlink(SupPid2), % otherwise we crash with it + {ok, CPid1} = supervisor:start_child(SupPid1, Child1), + {ok, _CPid2} = supervisor:start_child(SupPid1, Child2), + {ok, CPid3} = supervisor:start_child(SupPid2, Child1), + {ok, _CPid4} = supervisor:start_child(SupPid2, Child2), + terminate(SupPid1, CPid1, child1, normal), + terminate(SupPid2, CPid3, child1, normal), + timer:sleep(350), + catch link(SupPid1), + catch link(SupPid2), + %% The supervisor would die attempting to restart child2 + true = erlang:is_process_alive(SupPid1), + true = erlang:is_process_alive(SupPid2), + %% Child2 has not been restarted + [{child1, _, _, _}] = supervisor:which_children(SupPid1), + [{child1, _, _, _}] = supervisor:which_children(SupPid2). + +%%------------------------------------------------------------------------- one_for_one(doc) -> ["Test the one_for_one base case."]; one_for_one(suite) -> []; one_for_one(Config) when is_list(Config) -> process_flag(trap_exit, true), Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, - worker, []}, + worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000, - worker, []}, - ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), - link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - test_server:sleep(100), + worker, []}, + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), + + terminate(SupPid, CPid1, child1, abnormal), Children = supervisor:which_children(sup_test), if length(Children) == 2 -> case lists:keysearch(CPid2, 2, Children) of {value, _} -> ok; - _ -> ?line test_server:fail(bad_child) + _ -> test_server:fail(bad_child) end; - true -> ?line test_server:fail({bad_child_list, Children}) + true -> test_server:fail({bad_child_list, Children}) end, - ?line [2,2,0,2] = get_child_counts(sup_test), - + [2,2,0,2] = get_child_counts(sup_test), + %% Test restart frequency property - CPid2 ! die, - receive - {'EXIT', CPid2, _} -> ok - end, - test_server:sleep(100), - [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test), - Pid4 ! die, - receive - {'EXIT', Pid, _} -> ok - after 3000 -> ?line test_server:fail(restart_failed) - end, - ok. -%------------------------------------------------------------------------- + terminate(SupPid, CPid2, child2, abnormal), + + [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test), + terminate(SupPid, Pid4, Id4, abnormal), + check_exit([SupPid]). + +%%------------------------------------------------------------------------- one_for_one_escalation(doc) -> ["Test restart escalation on a one_for_one supervisor."]; one_for_one_escalation(suite) -> []; one_for_one_escalation(Config) when is_list(Config) -> process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, [error]}, permanent, 1000, - worker, []}, + worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000, - worker, []}, - ?line {ok, Pid} = start({ok, {{one_for_one, 4, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + worker, []}, + + {ok, SupPid} = start_link({ok, {{one_for_one, 4, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - receive - {'EXIT', Pid, _} -> ok - after - 2000 -> ?line test_server:fail(supervisor_alive) - end, - receive - {'EXIT', CPid2, _} -> ok - after - 4000 -> ?line test_server:fail(all_not_terminated) - end, - ok. -%------------------------------------------------------------------------- + + terminate(SupPid, CPid1, child1, abnormal), + check_exit([SupPid, CPid2]). + + +%%------------------------------------------------------------------------- one_for_all(doc) -> ["Test the one_for_all base case."]; one_for_all(suite) -> []; one_for_all(Config) when is_list(Config) -> process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{one_for_all, 2, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, SupPid} = start_link({ok, {{one_for_all, 2, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - receive - {'EXIT', CPid2, _} -> ok - end, - test_server:sleep(100), + + terminate(SupPid, CPid1, child1, abnormal), + check_exit([CPid2]), + Children = supervisor:which_children(sup_test), if length(Children) == 2 -> ok; - true -> ?line test_server:fail({bad_child_list, Children}) + true -> + test_server:fail({bad_child_list, Children}) end, + %% Test that no old children is still alive - SCh = lists:map(fun({_,P,_,_}) -> P end, Children), - case lists:member(CPid1, SCh) of - true -> ?line test_server:fail(bad_child); - false -> ok - end, - case lists:member(CPid2, SCh) of - true -> ?line test_server:fail(bad_child); - false -> ok - end, - ?line [2,2,0,2] = get_child_counts(sup_test), + not_in_child_list([CPid1, CPid2], lists:map(fun({_,P,_,_}) -> P end, Children)), + + [2,2,0,2] = get_child_counts(sup_test), %%% Test restart frequency property - [{_, Pid3, _, _}|_] = supervisor:which_children(sup_test), - Pid3 ! die, - test_server:sleep(100), - [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test), - Pid4 ! die, - receive - {'EXIT', Pid, _} -> ok - after 3000 -> ?line test_server:fail(restart_failed) - end, - exit(Pid, shutdown). + [{Id3, Pid3, _, _}|_] = supervisor:which_children(sup_test), + terminate(SupPid, Pid3, Id3, abnormal), + [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test), + terminate(SupPid, Pid4, Id4, abnormal), + check_exit([SupPid]). + -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- one_for_all_escalation(doc) -> ["Test restart escalation on a one_for_all supervisor."]; one_for_all_escalation(suite) -> []; one_for_all_escalation(Config) when is_list(Config) -> process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, Child2 = {child2, {supervisor_1, start_child, [error]}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{one_for_all, 4, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, SupPid} = start_link({ok, {{one_for_all, 4, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - receive - {'EXIT', CPid2, _} -> ok - after - 2000 -> ?line test_server:fail(all_not_terminated) - end, - receive - {'EXIT', Pid, _} -> ok - after - 4000 -> ?line test_server:fail(supervisor_alive) - end, - ok. -%------------------------------------------------------------------------- + terminate(SupPid, CPid1, child1, abnormal), + check_exit([CPid2, SupPid]). + + +%%------------------------------------------------------------------------- simple_one_for_one(doc) -> ["Test the simple_one_for_one base case."]; simple_one_for_one(suite) -> []; @@ -888,42 +844,31 @@ simple_one_for_one(Config) when is_list(Config) -> process_flag(trap_exit, true), Child = {child, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, []), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, []), - link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - test_server:sleep(100), + {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + {ok, CPid1} = supervisor:start_child(sup_test, []), + {ok, CPid2} = supervisor:start_child(sup_test, []), + + terminate(SupPid, CPid1, child1, abnormal), + Children = supervisor:which_children(sup_test), if length(Children) == 2 -> case lists:keysearch(CPid2, 2, Children) of {value, _} -> ok; - _ -> ?line test_server:fail(bad_child) + _ -> test_server:fail(bad_child) end; - true -> ?line test_server:fail({bad_child_list, Children}) + true -> test_server:fail({bad_child_list, Children}) end, - ?line [1,2,0,2] = get_child_counts(sup_test), + [1,2,0,2] = get_child_counts(sup_test), %% Test restart frequency property - CPid2 ! die, - receive - {'EXIT', CPid2, _} -> ok - end, - test_server:sleep(100), - [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test), - Pid4 ! die, - receive - {'EXIT', Pid, _} -> ok - after 3000 -> ?line test_server:fail(restart_failed) - end, - ok. -%------------------------------------------------------------------------- + terminate(SupPid, CPid2, child2, abnormal), + + [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test), + + terminate(SupPid, Pid4, Id4, abnormal), + check_exit([SupPid]). + +%%------------------------------------------------------------------------- simple_one_for_one_extra(doc) -> ["Tests automatic restart of children " "who's start function return extra info."]; @@ -932,41 +877,26 @@ simple_one_for_one_extra(Config) when is_list(Config) -> process_flag(trap_exit, true), Child = {child, {supervisor_1, start_child, [extra_info]}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), - ?line {ok, CPid1, extra_info} = supervisor:start_child(sup_test, []), - link(CPid1), - ?line {ok, CPid2, extra_info} = supervisor:start_child(sup_test, []), + {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + {ok, CPid1, extra_info} = supervisor:start_child(sup_test, []), + {ok, CPid2, extra_info} = supervisor:start_child(sup_test, []), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - test_server:sleep(100), + terminate(SupPid, CPid1, child1, abnormal), Children = supervisor:which_children(sup_test), if length(Children) == 2 -> case lists:keysearch(CPid2, 2, Children) of {value, _} -> ok; - _ -> ?line test_server:fail(bad_child) + _ -> test_server:fail(bad_child) end; - true -> ?line test_server:fail({bad_child_list, Children}) + true -> test_server:fail({bad_child_list, Children}) end, - ?line [1,2,0,2] = get_child_counts(sup_test), + [1,2,0,2] = get_child_counts(sup_test), + terminate(SupPid, CPid2, child2, abnormal), + [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test), + terminate(SupPid, Pid4, Id4, abnormal), + check_exit([SupPid]). - CPid2 ! die, - receive - {'EXIT', CPid2, _} -> ok - end, - test_server:sleep(100), - [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test), - Pid4 ! die, - receive - {'EXIT', Pid, _} -> ok - after 3000 -> ?line test_server:fail(restart_failed) - end, - ok. -%------------------------------------------------------------------------- +%%------------------------------------------------------------------------- simple_one_for_one_escalation(doc) -> ["Test restart escalation on a simple_one_for_one supervisor."]; simple_one_for_one_escalation(suite) -> []; @@ -974,29 +904,16 @@ simple_one_for_one_escalation(Config) when is_list(Config) -> process_flag(trap_exit, true), Child = {child, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{simple_one_for_one, 4, 3600}, [Child]}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, [error]), + {ok, SupPid} = start_link({ok, {{simple_one_for_one, 4, 3600}, [Child]}}), + {ok, CPid1} = supervisor:start_child(sup_test, [error]), link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, []), + {ok, CPid2} = supervisor:start_child(sup_test, []), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - receive - {'EXIT', Pid, _} -> ok - after - 2000 -> ?line test_server:fail(supervisor_alive) - end, - receive - {'EXIT', CPid2, _} -> ok - after - 2000 -> ?line test_server:fail(all_not_terminated) - end, - ok. -%------------------------------------------------------------------------- + + terminate(SupPid, CPid1, child, abnormal), + check_exit([SupPid, CPid2]). + +%%------------------------------------------------------------------------- rest_for_one(doc) -> ["Test the rest_for_one base case."]; rest_for_one(suite) -> []; @@ -1008,70 +925,45 @@ rest_for_one(Config) when is_list(Config) -> worker, []}, Child3 = {child3, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{rest_for_one, 2, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, SupPid} = start_link({ok, {{rest_for_one, 2, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), - link(CPid2), - ?line {ok, CPid3} = supervisor:start_child(sup_test, Child3), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, CPid3} = supervisor:start_child(sup_test, Child3), link(CPid3), - ?line [3,3,0,3] = get_child_counts(sup_test), + [3,3,0,3] = get_child_counts(sup_test), + + terminate(SupPid, CPid2, child2, abnormal), - CPid2 ! die, - receive - {'EXIT', CPid2, died} -> ok; - {'EXIT', CPid2, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - after 2000 -> - ?line test_server:fail(no_exit) - end, %% Check that Cpid3 did die - receive - {'EXIT', CPid3, _} -> ok - after 2000 -> - ?line test_server:fail(no_exit) - end, - %% Check that Cpid1 didn't die - receive - {'EXIT', CPid1, _} -> - ?line test_server:fail(bad_exit) - after - 100 -> ok - end, + check_exit([CPid3]), + Children = supervisor:which_children(sup_test), - if length(Children) == 3 -> ok; - true -> ?line test_server:fail({bad_child_list, Children}) + is_in_child_list([CPid1], Children), + + if length(Children) == 3 -> + ok; + true -> + test_server:fail({bad_child_list, Children}) end, - ?line [3,3,0,3] = get_child_counts(sup_test), + [3,3,0,3] = get_child_counts(sup_test), %% Test that no old children is still alive - SCh = lists:map(fun({_,P,_,_}) -> P end, Children), - case lists:member(CPid1, SCh) of - true -> ok; - false -> ?line test_server:fail(bad_child) - end, - case lists:member(CPid2, SCh) of - true -> ?line test_server:fail(bad_child); - false -> ok - end, - case lists:member(CPid3, SCh) of - true -> ?line test_server:fail(bad_child); - false -> ok - end, - + Pids = lists:map(fun({_,P,_,_}) -> P end, Children), + not_in_child_list([CPid2, CPid3], Pids), + in_child_list([CPid1], Pids), + %% Test restart frequency property [{child3, Pid3, _, _}|_] = supervisor:which_children(sup_test), - Pid3 ! die, - test_server:sleep(100), + + terminate(SupPid, Pid3, child3, abnormal), + [_,{child2, Pid4, _, _}|_] = supervisor:which_children(sup_test), - Pid4 ! die, - receive - {'EXIT', Pid, _} -> ok - after 3000 -> ?line test_server:fail(restart_failed) - end, - exit(Pid, shutdown). -%------------------------------------------------------------------------- + terminate(SupPid, Pid4, child2, abnormal), + check_exit([SupPid]). + +%%------------------------------------------------------------------------- rest_for_one_escalation(doc) -> ["Test restart escalation on a rest_for_one supervisor."]; rest_for_one_escalation(suite) -> []; @@ -1082,42 +974,29 @@ rest_for_one_escalation(Config) when is_list(Config) -> Child2 = {child2, {supervisor_1, start_child, [error]}, permanent, 1000, worker, []}, - ?line {ok, Pid} = start({ok, {{rest_for_one, 4, 3600}, []}}), - ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1), - link(CPid1), - ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2), + {ok, SupPid} = start_link({ok, {{rest_for_one, 4, 3600}, []}}), + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), link(CPid2), - CPid1 ! die, - receive - {'EXIT', CPid1, died} -> ok; - {'EXIT', CPid1, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - end, - receive - {'EXIT', CPid2, _} -> ok - after - 2000 -> ?line test_server:fail(not_terminated) - end, - receive - {'EXIT', Pid, _} -> ok - after - 4000 -> ?line test_server:fail(supervisor_alive) - end, - ok. -%------------------------------------------------------------------------- -child_unlink(doc)-> ["Test that the supervisor does not hang forever if " - "the child unliks and then is terminated by the supervisor."]; -child_unlink(suite) -> []; + terminate(SupPid, CPid1, child1, abnormal), + check_exit([CPid2, SupPid]). + +%%------------------------------------------------------------------------- +child_unlink(doc)-> + ["Test that the supervisor does not hang forever if " + "the child unliks and then is terminated by the supervisor."]; +child_unlink(suite) -> + []; child_unlink(Config) when is_list(Config) -> - - ?line {ok, SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}), - + + {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child = {naughty_child, {naughty_child, start_link, [SupPid]}, permanent, 1000, worker, [supervisor_SUITE]}, - - ?line {ok, _ChildPid} = supervisor:start_child(sup_test, Child), + + {ok, _ChildPid} = supervisor:start_child(sup_test, Child), Pid = spawn(supervisor, terminate_child, [SupPid, naughty_child]), @@ -1130,17 +1009,16 @@ child_unlink(Config) when is_list(Config) -> ok; _ -> exit(Pid, kill), - ?line test_server:fail(supervisor_hangs) + test_server:fail(supervisor_hangs) end. -%------------------------------------------------------------------------- - +%%------------------------------------------------------------------------- tree(doc) -> ["Test a basic supervison tree."]; tree(suite) -> []; tree(Config) when is_list(Config) -> process_flag(trap_exit, true), - + Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, @@ -1166,109 +1044,54 @@ tree(Config) when is_list(Config) -> supervisor, []}, %% Top supervisor - ?line {ok, Pid} = start({ok, {{one_for_all, 4, 3600}, []}}), - + {ok, SupPid} = start_link({ok, {{one_for_all, 4, 3600}, []}}), + %% Child supervisors - ?line {ok, Sup1} = supervisor:start_child(Pid, ChildSup1), - ?line {ok, Sup2} = supervisor:start_child(Pid, ChildSup2), - ?line [2,2,2,0] = get_child_counts(Pid), - + {ok, Sup1} = supervisor:start_child(SupPid, ChildSup1), + {ok, Sup2} = supervisor:start_child(SupPid, ChildSup2), + [2,2,2,0] = get_child_counts(SupPid), + %% Workers - ?line [{_, CPid2, _, _},{_, CPid1, _, _}] = + [{_, CPid2, _, _},{_, CPid1, _, _}] = supervisor:which_children(Sup1), - ?line [2,2,0,2] = get_child_counts(Sup1), - ?line [0,0,0,0] = get_child_counts(Sup2), - + [2,2,0,2] = get_child_counts(Sup1), + [0,0,0,0] = get_child_counts(Sup2), + %% Dynamic children - ?line {ok, CPid3} = supervisor:start_child(Sup2, Child3), - ?line {ok, CPid4} = supervisor:start_child(Sup2, Child4), - ?line [2,2,0,2] = get_child_counts(Sup1), - ?line [2,2,0,2] = get_child_counts(Sup2), - - link(Sup1), - link(Sup2), - link(CPid1), - link(CPid2), - link(CPid3), - link(CPid4), - + {ok, CPid3} = supervisor:start_child(Sup2, Child3), + {ok, CPid4} = supervisor:start_child(Sup2, Child4), + [2,2,0,2] = get_child_counts(Sup1), + [2,2,0,2] = get_child_counts(Sup2), + %% Test that the only the process that dies is restarted - CPid4 ! die, - - receive - {'EXIT', CPid4, _} -> ?line ok - after 10000 -> - ?line test_server:fail(child_was_not_killed) - end, - - test_server:sleep(100), - - ?line [{_, CPid2, _, _},{_, CPid1, _, _}] = + terminate(Sup2, CPid4, child4, abnormal), + + [{_, CPid2, _, _},{_, CPid1, _, _}] = supervisor:which_children(Sup1), - ?line [2,2,0,2] = get_child_counts(Sup1), - - ?line [{_, NewCPid4, _, _},{_, CPid3, _, _}] = + [2,2,0,2] = get_child_counts(Sup1), + + [{_, NewCPid4, _, _},{_, CPid3, _, _}] = supervisor:which_children(Sup2), - ?line [2,2,0,2] = get_child_counts(Sup2), - - link(NewCPid4), + [2,2,0,2] = get_child_counts(Sup2), + + false = NewCPid4 == CPid4, %% Test that supervisor tree is restarted, but not dynamic children. - CPid3 ! die, + terminate(Sup2, CPid3, child3, abnormal), - receive - {'EXIT', CPid3, died} -> ?line ok; - {'EXIT', CPid3, Reason} -> - ?line test_server:fail({bad_exit_reason, Reason}) - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, + timer:sleep(1000), - test_server:sleep(1000), + [{supchild2, NewSup2, _, _},{supchild1, NewSup1, _, _}] = + supervisor:which_children(SupPid), + [2,2,2,0] = get_child_counts(SupPid), - receive - {'EXIT', NewCPid4, _} -> ?line ok - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, - - receive - {'EXIT', Sup2, _} -> ?line ok - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, - - receive - {'EXIT', CPid1, _} -> ?line ok - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, - - receive - {'EXIT', CPid2, _} -> ?line ok - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, - - receive - {'EXIT', Sup1, _} -> ?line ok - after 1000 -> - ?line test_server:fail(child_was_not_killed) - end, - - ?line [{supchild2, NewSup2, _, _},{supchild1, NewSup1, _, _}] = - supervisor:which_children(Pid), - ?line [2,2,2,0] = get_child_counts(Pid), - - ?line [{child2, _, _, _},{child1, _, _, _}] = + [{child2, _, _, _},{child1, _, _, _}] = supervisor:which_children(NewSup1), - ?line [2,2,0,2] = get_child_counts(NewSup1), + [2,2,0,2] = get_child_counts(NewSup1), - ?line [] = supervisor:which_children(NewSup2), - ?line [0,0,0,0] = get_child_counts(NewSup2), - - ok. -%------------------------------------------------------------------------- + [] = supervisor:which_children(NewSup2), + [0,0,0,0] = get_child_counts(NewSup2). +%%------------------------------------------------------------------------- count_children_memory(doc) -> ["Test that count_children does not eat memory."]; count_children_memory(suite) -> @@ -1277,7 +1100,7 @@ count_children_memory(Config) when is_list(Config) -> process_flag(trap_exit, true), Child = {child, {supervisor_1, start_child, []}, temporary, 1000, worker, []}, - ?line {ok, _Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), [supervisor:start_child(sup_test, []) || _Ignore <- lists:seq(1,1000)], garbage_collect(), @@ -1301,12 +1124,12 @@ count_children_memory(Config) when is_list(Config) -> ChildCount3 = get_child_counts(sup_test), Size7 = erlang:memory(processes_used), - ?line 1000 = length(Children), - ?line [1,1000,0,1000] = ChildCount, - ?line 2000 = length(Children2), - ?line [1,2000,0,2000] = ChildCount2, - ?line Children3 = Children2, - ?line ChildCount3 = ChildCount2, + 1000 = length(Children), + [1,1000,0,1000] = ChildCount, + 2000 = length(Children2), + [1,2000,0,2000] = ChildCount2, + Children3 = Children2, + ChildCount3 = ChildCount2, %% count_children consumes memory using an accumulator function, %% but the space can be reclaimed incrementally, @@ -1314,29 +1137,18 @@ count_children_memory(Config) when is_list(Config) -> case (Size5 =< Size4) of true -> ok; false -> - ?line test_server:fail({count_children, used_more_memory}) + test_server:fail({count_children, used_more_memory}) end, case Size7 =< Size6 of true -> ok; false -> - ?line test_server:fail({count_children, used_more_memory}) + test_server:fail({count_children, used_more_memory}) end, - [exit(Pid, kill) || {undefined, Pid, worker, _Modules} <- Children3], - test_server:sleep(100), - ?line [1,0,0,0] = get_child_counts(sup_test), - ok. -count_children_allocator_test(MemoryState) -> - Allocators = [temp_alloc, eheap_alloc, binary_alloc, ets_alloc, - driver_alloc, sl_alloc, ll_alloc, fix_alloc, std_alloc, - sys_alloc], - MemoryStateList = element(4, MemoryState), - AllocTypes = [lists:keyfind(Alloc, 1, MemoryStateList) - || Alloc <- Allocators], - AllocStates = [lists:keyfind(e, 1, AllocValue) - || {_Type, AllocValue} <- AllocTypes], - lists:all(fun(State) -> State == {e, true} end, AllocStates). -%------------------------------------------------------------------------- + [terminate(SupPid, Pid, child, kill) || {undefined, Pid, worker, _Modules} <- Children3], + [1,0,0,0] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- do_not_save_start_parameters_for_temporary_children(doc) -> ["Temporary children shall not be restarted so they should not " "save start parameters, as it potentially can " @@ -1350,6 +1162,44 @@ do_not_save_start_parameters_for_temporary_children(Config) when is_list(Config) dont_save_start_parameters_for_temporary_children(rest_for_one), dont_save_start_parameters_for_temporary_children(simple_one_for_one). +start_children(_,_, 0) -> + ok; +start_children(Sup, Args, N) -> + Spec = child_spec(Args, N), + {ok, _, _} = supervisor:start_child(Sup, Spec), + start_children(Sup, Args, N-1). + +child_spec([_|_] = SimpleOneForOneArgs, _) -> + SimpleOneForOneArgs; +child_spec({Name, MFA, RestartType, Shutdown, Type, Modules}, N) -> + NewName = list_to_atom((atom_to_list(Name) ++ integer_to_list(N))), + {NewName, MFA, RestartType, Shutdown, Type, Modules}. + +%%------------------------------------------------------------------------- +do_not_save_child_specs_for_temporary_children(doc) -> + ["Temporary children shall not be restarted so supervisors should " + "not save their spec when they terminate"]; +do_not_save_child_specs_for_temporary_children(suite) -> + []; +do_not_save_child_specs_for_temporary_children(Config) when is_list(Config) -> + process_flag(trap_exit, true), + dont_save_child_specs_for_temporary_children(one_for_all, kill), + dont_save_child_specs_for_temporary_children(one_for_one, kill), + dont_save_child_specs_for_temporary_children(rest_for_one, kill), + + dont_save_child_specs_for_temporary_children(one_for_all, normal), + dont_save_child_specs_for_temporary_children(one_for_one, normal), + dont_save_child_specs_for_temporary_children(rest_for_one, normal), + + dont_save_child_specs_for_temporary_children(one_for_all, abnormal), + dont_save_child_specs_for_temporary_children(one_for_one, abnormal), + dont_save_child_specs_for_temporary_children(rest_for_one, abnormal), + + dont_save_child_specs_for_temporary_children(one_for_all, supervisor), + dont_save_child_specs_for_temporary_children(one_for_one, supervisor), + dont_save_child_specs_for_temporary_children(rest_for_one, supervisor). + +%%------------------------------------------------------------------------- dont_save_start_parameters_for_temporary_children(simple_one_for_one = Type) -> Permanent = {child, {supervisor_1, start_child, []}, permanent, 1000, worker, []}, @@ -1373,9 +1223,9 @@ dont_save_start_parameters_for_temporary_children(simple_one_for_one = Type) -> true = (Mem3 < Mem1) and (Mem3 < Mem2), - exit(Sup1, shutdown), - exit(Sup2, shutdown), - exit(Sup3, shutdown); + terminate(Sup1, shutdown), + terminate(Sup2, shutdown), + terminate(Sup3, shutdown); dont_save_start_parameters_for_temporary_children(Type) -> {ok, Sup1} = supervisor:start_link(?MODULE, {ok, {{Type, 2, 3600}, []}}), @@ -1401,19 +1251,187 @@ dont_save_start_parameters_for_temporary_children(Type) -> true = (Mem3 < Mem1) and (Mem3 < Mem2), - exit(Sup1, shutdown), - exit(Sup2, shutdown), - exit(Sup3, shutdown). + terminate(Sup1, shutdown), + terminate(Sup2, shutdown), + terminate(Sup3, shutdown). -start_children(_,_, 0) -> +dont_save_child_specs_for_temporary_children(Type, TerminateHow)-> + {ok, Sup} = + supervisor:start_link(?MODULE, {ok, {{Type, 2, 3600}, []}}), + + Permanent = {child1, {supervisor_1, start_child, []}, + permanent, 1000, worker, []}, + Transient = {child2, {supervisor_1, start_child, []}, + transient, 1000, worker, []}, + Temporary = {child3, {supervisor_1, start_child, []}, + temporary, 1000, worker, []}, + + permanent_child_spec_saved(Permanent, Sup, TerminateHow), + + transient_child_spec_saved(Transient, Sup, TerminateHow), + + temporary_child_spec_not_saved(Temporary, Sup, TerminateHow), + + terminate(Sup, shutdown). + +permanent_child_spec_saved(ChildSpec, Sup, supervisor = TerminateHow) -> + already_present(Sup, ChildSpec, TerminateHow); + +permanent_child_spec_saved(ChildSpec, Sup, TerminateHow) -> + restarted(Sup, ChildSpec, TerminateHow). + +transient_child_spec_saved(ChildSpec, Sup, supervisor = TerminateHow) -> + already_present(Sup, ChildSpec, TerminateHow); + +transient_child_spec_saved(ChildSpec, Sup, normal = TerminateHow) -> + already_present(Sup, ChildSpec, TerminateHow); + +transient_child_spec_saved(ChildSpec, Sup, TerminateHow) -> + restarted(Sup, ChildSpec, TerminateHow). + +temporary_child_spec_not_saved({Id, _,_,_,_,_} = ChildSpec, Sup, TerminateHow) -> + {ok, Pid} = supervisor:start_child(Sup, ChildSpec), + terminate(Sup, Pid, Id, TerminateHow), + {ok, _} = supervisor:start_child(Sup, ChildSpec). + +already_present(Sup, {Id,_,_,_,_,_} = ChildSpec, TerminateHow) -> + {ok, Pid} = supervisor:start_child(Sup, ChildSpec), + terminate(Sup, Pid, Id, TerminateHow), + {error, already_present} = supervisor:start_child(Sup, ChildSpec), + {ok, _} = supervisor:restart_child(Sup, Id). + +restarted(Sup, {Id,_,_,_,_,_} = ChildSpec, TerminateHow) -> + {ok, Pid} = supervisor:start_child(Sup, ChildSpec), + terminate(Sup, Pid, Id, TerminateHow), + %% Permanent processes will be restarted by the supervisor + %% when not terminated by api + {error, {already_started, _}} = supervisor:start_child(Sup, ChildSpec). + + +%%------------------------------------------------------------------------- +%% OTP-9242: Pids for dynamic temporary children were saved as a list, +%% which caused bad scaling when adding/deleting many processes. +simple_one_for_one_scale_many_temporary_children(_Config) -> + process_flag(trap_exit, true), + Child = {child, {supervisor_1, start_child, []}, temporary, 1000, + worker, []}, + {ok, _SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}), + + C1 = [begin + {ok,P} = supervisor:start_child(sup_test,[]), + P + end || _<- lists:seq(1,1000)], + {T1,done} = timer:tc(?MODULE,terminate_all_children,[C1]), + + C2 = [begin + {ok,P} = supervisor:start_child(sup_test,[]), + P + end || _<- lists:seq(1,10000)], + {T2,done} = timer:tc(?MODULE,terminate_all_children,[C2]), + + Scaling = T2 div T1, + if Scaling > 20 -> + %% The scaling shoul be linear (i.e.10, really), but we + %% give some extra here to avoid failing the test + %% unecessarily. + ?t:fail({bad_scaling,Scaling}); + true -> + ok + end. + + +terminate_all_children([C|Cs]) -> + ok = supervisor:terminate_child(sup_test,C), + terminate_all_children(Cs); +terminate_all_children([]) -> + done. + + + +%%------------------------------------------------------------------------- +terminate(Pid, Reason) when Reason =/= supervisor -> + terminate(dummy, Pid, dummy, Reason). + +terminate(Sup, _, ChildId, supervisor) -> + ok = supervisor:terminate_child(Sup, ChildId); +terminate(_, ChildPid, _, kill) -> + Ref = erlang:monitor(process, ChildPid), + exit(ChildPid, kill), + receive + {'DOWN', Ref, process, ChildPid, killed} -> + ok + end; +terminate(_, ChildPid, _, shutdown) -> + Ref = erlang:monitor(process, ChildPid), + exit(ChildPid, shutdown), + receive + {'DOWN', Ref, process, ChildPid, shutdown} -> + ok + end; +terminate(_, ChildPid, _, {shutdown, Term}) -> + Ref = erlang:monitor(process, ChildPid), + exit(ChildPid, {shutdown, Term}), + receive + {'DOWN', Ref, process, ChildPid, {shutdown, Term}} -> + ok + end; +terminate(_, ChildPid, _, normal) -> + Ref = erlang:monitor(process, ChildPid), + ChildPid ! stop, + receive + {'DOWN', Ref, process, ChildPid, normal} -> + ok + end; +terminate(_, ChildPid, _,abnormal) -> + Ref = erlang:monitor(process, ChildPid), + ChildPid ! die, + receive + {'DOWN', Ref, process, ChildPid, died} -> + ok + end. + +in_child_list([], _) -> + true; +in_child_list([Pid | Rest], Pids) -> + case is_in_child_list(Pid, Pids) of + true -> + in_child_list(Rest, Pids); + false -> + test_server:fail(child_should_be_alive) + end. +not_in_child_list([], _) -> + true; +not_in_child_list([Pid | Rest], Pids) -> + case is_in_child_list(Pid, Pids) of + true -> + test_server:fail(child_should_not_be_alive); + false -> + not_in_child_list(Rest, Pids) + end. + +is_in_child_list(Pid, ChildPids) -> + lists:member(Pid, ChildPids). + +check_exit([]) -> ok; -start_children(Sup, Args, N) -> - Spec = child_spec(Args, N), - {ok, _, _} = supervisor:start_child(Sup, Spec), - start_children(Sup, Args, N-1). +check_exit([Pid | Pids]) -> + receive + {'EXIT', Pid, _} -> + check_exit(Pids) + end. -child_spec([_|_] = SimpleOneForOneArgs, _) -> - SimpleOneForOneArgs; -child_spec({Name, MFA, RestartType, Shutdown, Type, Modules}, N) -> - NewName = list_to_atom((atom_to_list(Name) ++ integer_to_list(N))), - {NewName, MFA, RestartType, Shutdown, Type, Modules}. +check_exit_reason(Reason) -> + receive + {'EXIT', _, Reason} -> + ok; + {'EXIT', _, Else} -> + test_server:fail({bad_exit_reason, Else}) + end. + +check_exit_reason(Pid, Reason) -> + receive + {'EXIT', Pid, Reason} -> + ok; + {'EXIT', Pid, Else} -> + test_server:fail({bad_exit_reason, Else}) + end. diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl index f2dbad0b3b..c4d696564d 100644 --- a/lib/stdlib/test/supervisor_bridge_SUITE.erl +++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl @@ -158,7 +158,7 @@ internal_loop(State) -> terminate(Reason,{Parent,Worker}) -> %% This func knows about supervisor_bridge io:format("Terminating bridge...\n"), - exit(kill,Worker), + exit(Worker,kill), Parent ! {dying,Reason}, anything. diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl index 72b089aa3f..fe039e8bcc 100644 --- a/lib/stdlib/test/sys_SUITE.erl +++ b/lib/stdlib/test/sys_SUITE.erl @@ -71,7 +71,7 @@ log_to_file(Config) when is_list(Config) -> ?line ok = sys:log_to_file(?server,TempName), ?line {ok,-44} = public_call(44), ?line ok = sys:log_to_file(?server,false), - ?line {ok,Fd} = file:open(TempName,read), + ?line {ok,Fd} = file:open(TempName,[read]), ?line Msg1 = io:get_line(Fd,''), ?line Msg2 = io:get_line(Fd,''), ?line file:close(Fd), diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl index e32704ca65..9ad3936928 100644 --- a/lib/stdlib/test/tar_SUITE.erl +++ b/lib/stdlib/test/tar_SUITE.erl @@ -65,7 +65,7 @@ borderline(Config) when is_list(Config) -> ?line {ok, Cwd} = file:get_cwd(), ?line RootDir = ?config(priv_dir, Config), - ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, borderline)), + ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")), ?line ok = file:make_dir(TempDir), ?line Record = 512, @@ -283,17 +283,16 @@ long_names(doc) -> long_names(Config) when is_list(Config) -> ?line DataDir = ?config(data_dir, Config), ?line Long = filename:join(DataDir, "long_names.tar"), + run_in_short_tempdir(Config, + fun() -> do_long_names(Long) end). +do_long_names(Long) -> %% Try table/2 and extract/2. ?line case erl_tar:table(Long, [verbose]) of {ok,List} when is_list(List) -> ?line io:format("~p\n", [List]) end, - - %% To avoid getting too long paths for Windows to handle, extract into - %% the current directory (which is the test_server directory). Its path - %% is quite a bit shorter than the path to priv_dir. ?line {ok,Cwd} = file:get_cwd(), ?line ok = erl_tar:extract(Long), ?line Base = filename:join([Cwd, "original_software", "written_by", @@ -312,29 +311,28 @@ long_names(Config) when is_list(Config) -> ?line "Here"++_ = binary_to_list(First), ?line "And"++_ = binary_to_list(Second), - %% Clean up. - ?line delete_files([filename:join(Cwd, "original_software"),EmptyDir]), - ok. create_long_names(doc) -> ["Creates a tar file from a deep directory structure (filenames are ", "longer than 100 characters)."]; create_long_names(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line ok = file:set_cwd(PrivDir), - Dirs = [aslfjkshjkhliuf, - asdhjfehnbfsky, - sahajfskdfhsz, - asldfkdlfy4y8rchg, - f7nafhjgffagkhsfkhsjk, - dfjasldkfjsdkfjashbv], + run_in_short_tempdir(Config, fun create_long_names/0). + +create_long_names() -> + ?line {ok,Dir} = file:get_cwd(), + Dirs = ["aslfjkshjkhliuf", + "asdhjfehnbfsky", + "sahajfskdfhsz", + "asldfkdlfy4y8rchg", + "f7nafhjgffagkhsfkhsjk", + "dfjasldkfjsdkfjashbv"], ?line DeepDir = make_dirs(Dirs, []), ?line AFile = filename:join(DeepDir, "a_file"), ?line Hello = "hello, world\n", ?line ok = file:write_file(AFile, Hello), - ?line TarName = filename:join(PrivDir, "my_tar_with_long_names.tar"), + ?line TarName = filename:join(Dir, "my_tar_with_long_names.tar"), ?line ok = erl_tar:create(TarName, [AFile]), %% Print contents. @@ -347,9 +345,6 @@ create_long_names(Config) when is_list(Config) -> ?line {ok, Bin} = file:read_file(filename:join(ExtractDir, AFile)), ?line Hello = binary_to_list(Bin), - %% Clean up. - ?line delete_files([ExtractDir,TarName,hd(Dirs)]), - ok. make_dirs([Dir|Rest], []) -> @@ -487,7 +482,7 @@ extract_from_binary_compressed(Config) when is_list(Config) -> %% Trying extracting from a binary. ?line ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]), - ?line {ok,List} = file:list_dir(filename:join(ExtractDir, ddll_SUITE_data)), + ?line {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")), ?line io:format("~p\n", [List]), ?line 19 = length(List), @@ -676,7 +671,7 @@ cooked_compressed(Config) when is_list(Config) -> end, List), %% Clean up. - ?line delete_files([filename:join(PrivDir, ddll_SUITE_data)]), + ?line delete_files([filename:join(PrivDir, "ddll_SUITE_data")]), ok. memory(doc) -> @@ -734,3 +729,42 @@ delete_files([Item|Rest]) -> end, delete_files(Rest). +%% Move to a temporary directory with as short name as possible and +%% execute Fun. Remove the directory and any files in it afterwards. +%% This is necessary because pathnames on Windows may be limited to +%% 260 characters. +run_in_short_tempdir(Config, Fun) -> + {ok,Cwd} = file:get_cwd(), + PrivDir0 = ?config(priv_dir, Config), + + %% Normalize name to make sure that there is no slash at the end. + PrivDir = filename:absname(PrivDir0), + + %% We need a base directory with a much shorter pathname than + %% priv_dir. We KNOW that priv_dir is located four levels below + %% the directory that common_test puts the ct_run.* directories + %% in. That fact is not documented, but an usually reliable source + %% assured me that the directory structure is unlikely to change + %% in future versions of common_test because of backward + %% compatibility (tools developed by users of common_test depend + %% on the current directory layout). + Base = lists:foldl(fun(_, D) -> + filename:dirname(D) + end, PrivDir, [1,2,3,4]), + + Dir = make_temp_dir(Base, 0), + ok = file:set_cwd(Dir), + io:format("Running test in ~s\n", [Dir]), + try + Fun() + after + file:set_cwd(Cwd), + delete_files([Dir]) + end. + +make_temp_dir(Base, I) -> + Name = filename:join(Base, integer_to_list(I, 36)), + case file:make_dir(Name) of + ok -> Name; + {error,eexist} -> make_temp_dir(Base, I+1) + end. diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl index 852afa1a4d..dc751aad16 100644 --- a/lib/stdlib/test/timer_simple_SUITE.erl +++ b/lib/stdlib/test/timer_simple_SUITE.erl @@ -229,7 +229,7 @@ cancel2(Config) when is_list(Config) -> tc(doc) -> "Test sleep/1 and tc/3."; tc(suite) -> []; tc(Config) when is_list(Config) -> - % This should both sleep and tc/3 + %% This should test both sleep and tc/3 ?line {Res1, ok} = timer:tc(timer, sleep, [500]), ?line ok = if Res1 < 500*1000 -> {too_early, Res1}; % Too early @@ -237,13 +237,40 @@ tc(Config) when is_list(Config) -> true -> ok end, - % This should both sleep and tc/2 + %% tc/2 ?line {Res2, ok} = timer:tc(fun(T) -> timer:sleep(T) end, [500]), ?line ok = if Res2 < 500*1000 -> {too_early, Res2}; % Too early Res2 > 800*1000 -> {too_late, Res2}; % Too much time true -> ok end, + + %% tc/1 + ?line {Res3, ok} = timer:tc(fun() -> timer:sleep(500) end), + ?line ok = if + Res3 < 500*1000 -> {too_early, Res3}; % Too early + Res3 > 800*1000 -> {too_late, Res3}; % Too much time + true -> ok + end, + + %% Check that timer:tc don't catch errors + ?line ok = try timer:tc(erlang, exit, [foo]) + catch exit:foo -> ok + end, + + ?line ok = try timer:tc(fun(Reason) -> 1 = Reason end, [foo]) + catch error:{badmatch,_} -> ok + end, + + ?line ok = try timer:tc(fun() -> throw(foo) end) + catch foo -> ok + end, + + %% Check that return values are propageted + Self = self(), + ?line {_, Self} = timer:tc(erlang, self, []), + ?line {_, Self} = timer:tc(fun(P) -> P end, [self()]), + ?line {_, Self} = timer:tc(fun() -> self() end), ?line Sec = timer:seconds(4), ?line Min = timer:minutes(4), diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl index d5f2cd52d4..7233c061ef 100644 --- a/lib/stdlib/test/zip_SUITE.erl +++ b/lib/stdlib/test/zip_SUITE.erl @@ -375,7 +375,8 @@ zip_options(Config) when is_list(Config) -> ok = file:set_cwd(?config(data_dir, Config)), %% Create a zip archive - {ok, Zip} = zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]), + {ok, {_,Zip}} = + zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]), %% Open archive {ok, ZipSrv} = zip:zip_open(Zip, [memory]), diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index c0956030cf..2f0ecd3863 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 1.17.4 +STDLIB_VSN = 1.18 |