diff options
Diffstat (limited to 'lispref/processes.texi')
| -rw-r--r-- | lispref/processes.texi | 425 |
1 files changed, 416 insertions, 9 deletions
diff --git a/lispref/processes.texi b/lispref/processes.texi index 07a72886355..f88b2c46159 100644 --- a/lispref/processes.texi +++ b/lispref/processes.texi | |||
| @@ -52,6 +52,7 @@ This function returns @code{t} if @var{object} is a process, | |||
| 52 | * Datagrams:: UDP network connections. | 52 | * Datagrams:: UDP network connections. |
| 53 | * Low-Level Network:: Lower-level but more general function | 53 | * Low-Level Network:: Lower-level but more general function |
| 54 | to create connections and servers. | 54 | to create connections and servers. |
| 55 | * Byte Packing:: Using bindat to pack and unpack binary data. | ||
| 55 | @end menu | 56 | @end menu |
| 56 | 57 | ||
| 57 | @node Subprocess Creation | 58 | @node Subprocess Creation |
| @@ -168,7 +169,7 @@ function. | |||
| 168 | (shell-quote-argument "foo > bar") | 169 | (shell-quote-argument "foo > bar") |
| 169 | @result{} "foo\\ \\>\\ bar" | 170 | @result{} "foo\\ \\>\\ bar" |
| 170 | 171 | ||
| 171 | ;; @r{This example shows the behavior on MS-DOS and MS-Windows systems.} | 172 | ;; @r{This example shows the behavior on MS-DOS and MS-Windows.} |
| 172 | (shell-quote-argument "foo > bar") | 173 | (shell-quote-argument "foo > bar") |
| 173 | @result{} "\"foo > bar\"" | 174 | @result{} "\"foo > bar\"" |
| 174 | @end example | 175 | @end example |
| @@ -766,9 +767,9 @@ specify the process to send input to, and the input data to send. The | |||
| 766 | data appears on the ``standard input'' of the subprocess. | 767 | data appears on the ``standard input'' of the subprocess. |
| 767 | 768 | ||
| 768 | Some operating systems have limited space for buffered input in a | 769 | Some operating systems have limited space for buffered input in a |
| 769 | @acronym{PTY}. On these systems, Emacs sends an @acronym{EOF} periodically amidst | 770 | @acronym{PTY}. On these systems, Emacs sends an @acronym{EOF} |
| 770 | the other characters, to force them through. For most programs, | 771 | periodically amidst the other characters, to force them through. For |
| 771 | these @acronym{EOF}s do no harm. | 772 | most programs, these @acronym{EOF}s do no harm. |
| 772 | 773 | ||
| 773 | Subprocess input is normally encoded using a coding system before the | 774 | Subprocess input is normally encoded using a coding system before the |
| 774 | subprocess receives it, much like text written into a file. You can use | 775 | subprocess receives it, much like text written into a file. You can use |
| @@ -972,7 +973,7 @@ primitive that waits. | |||
| 972 | @defvar process-adaptive-read-buffering | 973 | @defvar process-adaptive-read-buffering |
| 973 | On some systems, when Emacs reads the output from a subprocess, the | 974 | On some systems, when Emacs reads the output from a subprocess, the |
| 974 | output data is read in very small blocks, potentially resulting in | 975 | output data is read in very small blocks, potentially resulting in |
| 975 | very poor performance. This behaviour can be remedied to some extent | 976 | very poor performance. This behavior can be remedied to some extent |
| 976 | by setting the variable @var{process-adaptive-read-buffering} to a | 977 | by setting the variable @var{process-adaptive-read-buffering} to a |
| 977 | non-@code{nil} value (the default), as it will automatically delay reading | 978 | non-@code{nil} value (the default), as it will automatically delay reading |
| 978 | from such processes, thus allowing them to produce more output before | 979 | from such processes, thus allowing them to produce more output before |
| @@ -1559,7 +1560,7 @@ back to listening for more connection requests. | |||
| 1559 | keyword/argument pairs, for example @code{:server t} to create a | 1560 | keyword/argument pairs, for example @code{:server t} to create a |
| 1560 | server process, or @code{:type 'datagram} to create a datagram | 1561 | server process, or @code{:type 'datagram} to create a datagram |
| 1561 | connection. @xref{Low-Level Network}, for details. You can also use | 1562 | connection. @xref{Low-Level Network}, for details. You can also use |
| 1562 | the @code{open-network-stream} function descibed below. | 1563 | the @code{open-network-stream} function described below. |
| 1563 | 1564 | ||
| 1564 | You can distinguish process objects representing network connections | 1565 | You can distinguish process objects representing network connections |
| 1565 | and servers from those representing subprocesses with the | 1566 | and servers from those representing subprocesses with the |
| @@ -1823,7 +1824,8 @@ If you don't specify this keyword at all, the default | |||
| 1823 | is to determine the coding systems from the data. | 1824 | is to determine the coding systems from the data. |
| 1824 | 1825 | ||
| 1825 | @item :noquery @var{query-flag} | 1826 | @item :noquery @var{query-flag} |
| 1826 | Initialize the process query flag to @var{query-flag}. @xref{Query Before Exit}. | 1827 | Initialize the process query flag to @var{query-flag}. |
| 1828 | @xref{Query Before Exit}. | ||
| 1827 | 1829 | ||
| 1828 | @item :filter @var{filter} | 1830 | @item :filter @var{filter} |
| 1829 | Initialize the process filter to @var{filter}. | 1831 | Initialize the process filter to @var{filter}. |
| @@ -1938,7 +1940,8 @@ and @var{remote-address} arguments to @code{make-network-process}. | |||
| 1938 | 1940 | ||
| 1939 | @defun network-interface-info ifname | 1941 | @defun network-interface-info ifname |
| 1940 | This function returns information about the network interface named | 1942 | This function returns information about the network interface named |
| 1941 | @var{ifname}. The value is a list of the form @code{(@var{addr} @var{bcast} @var{netmask} @var{hwaddr} @var{flags})}. | 1943 | @var{ifname}. The value is a list of the form |
| 1944 | @code{(@var{addr} @var{bcast} @var{netmask} @var{hwaddr} @var{flags})}. | ||
| 1942 | 1945 | ||
| 1943 | @table @var | 1946 | @table @var |
| 1944 | @item addr | 1947 | @item addr |
| @@ -2015,7 +2018,411 @@ That particular network option is supported by | |||
| 2015 | @code{make-network-process} and @code{set-network-process-option}. | 2018 | @code{make-network-process} and @code{set-network-process-option}. |
| 2016 | @end table | 2019 | @end table |
| 2017 | 2020 | ||
| 2021 | @node Byte Packing | ||
| 2022 | @section Packing and Unpacking Byte Arrays | ||
| 2023 | |||
| 2024 | This section describes how to pack and unpack arrays of bytes, | ||
| 2025 | usually for binary network protocols. These functions convert byte arrays | ||
| 2026 | to alists, and vice versa. The byte array can be represented as a | ||
| 2027 | unibyte string or as a vector of integers, while the alist associates | ||
| 2028 | symbols either with fixed-size objects or with recursive sub-alists. | ||
| 2029 | |||
| 2030 | @cindex serializing | ||
| 2031 | @cindex deserializing | ||
| 2032 | @cindex packing | ||
| 2033 | @cindex unpacking | ||
| 2034 | Conversion from byte arrays to nested alists is also known as | ||
| 2035 | @dfn{deserializing} or @dfn{unpacking}, while going in the opposite | ||
| 2036 | direction is also known as @dfn{serializing} or @dfn{packing}. | ||
| 2037 | |||
| 2038 | @menu | ||
| 2039 | * Bindat Spec:: Describing data layout. | ||
| 2040 | * Bindat Functions:: Doing the unpacking and packing. | ||
| 2041 | * Bindat Examples:: Samples of what bindat.el can do for you! | ||
| 2042 | @end menu | ||
| 2043 | |||
| 2044 | @node Bindat Spec | ||
| 2045 | @subsection Describing Data Layout | ||
| 2046 | |||
| 2047 | To control unpacking and packing, you write a @dfn{data layout | ||
| 2048 | specification}, a special nested list describing named and typed | ||
| 2049 | @dfn{fields}. This specification controls length of each field to be | ||
| 2050 | processed, and how to pack or unpack it. | ||
| 2051 | |||
| 2052 | @cindex endianness | ||
| 2053 | @cindex big endian | ||
| 2054 | @cindex little endian | ||
| 2055 | @cindex network byte ordering | ||
| 2056 | A field's @dfn{type} describes the size (in bytes) of the object | ||
| 2057 | that the field represents and, in the case of multibyte fields, how | ||
| 2058 | the bytes are ordered within the field. The two possible orderings | ||
| 2059 | are ``big endian'' (also known as ``network byte ordering'') and | ||
| 2060 | ``little endian''. For instance, the number @code{#x23cd} (decimal | ||
| 2061 | 9165) in big endian would be the two bytes @code{#x23} @code{#xcd}; | ||
| 2062 | and in little endian, @code{#xcd} @code{#x23}. Here are the possible | ||
| 2063 | type values: | ||
| 2064 | |||
| 2065 | @table @code | ||
| 2066 | @item u8 | ||
| 2067 | @itemx byte | ||
| 2068 | Unsigned byte, with length 1. | ||
| 2069 | |||
| 2070 | @item u16 | ||
| 2071 | @itemx word | ||
| 2072 | @itemx short | ||
| 2073 | Unsigned integer in network byte order, with length 2. | ||
| 2074 | |||
| 2075 | @item u24 | ||
| 2076 | Unsigned integer in network byte order, with length 3. | ||
| 2077 | |||
| 2078 | @item u32 | ||
| 2079 | @itemx dword | ||
| 2080 | @itemx long | ||
| 2081 | Unsigned integer in network byte order, with length 4. | ||
| 2082 | Note: These values may be limited by Emacs' integer implementation limits. | ||
| 2083 | |||
| 2084 | @item u16r | ||
| 2085 | @itemx u24r | ||
| 2086 | @itemx u32r | ||
| 2087 | Unsigned integer in little endian order, with length 2, 3 and 4, respectively. | ||
| 2088 | |||
| 2089 | @item str @var{len} | ||
| 2090 | String of length @var{len}. | ||
| 2091 | |||
| 2092 | @item strz @var{len} | ||
| 2093 | Zero-terminated string of length @var{len}. | ||
| 2094 | |||
| 2095 | @item vec @var{len} | ||
| 2096 | Vector of @var{len} bytes. | ||
| 2097 | |||
| 2098 | @item ip | ||
| 2099 | Four-byte vector representing an Internet address. For example: | ||
| 2100 | @code{[127 0 0 1]} for localhost. | ||
| 2101 | |||
| 2102 | @item bits @var{len} | ||
| 2103 | List of set bits in @var{len} bytes. The bytes are taken in big | ||
| 2104 | endian order and the bits are numbered starting with @code{8 * | ||
| 2105 | @var{len} @minus{} 1} and ending with zero. For example: @code{bits | ||
| 2106 | 2} unpacks @code{#x28} @code{#x1c} to @code{(2 3 4 11 13)} and | ||
| 2107 | @code{#x1c} @code{#x28} to @code{(3 5 10 11 12)}. | ||
| 2108 | |||
| 2109 | @item (eval @var{form}) | ||
| 2110 | @var{form} is a Lisp expression evaluated at the moment the field is | ||
| 2111 | unpacked or packed. The result of the evaluation should be one of the | ||
| 2112 | above-listed type specifications. | ||
| 2113 | @end table | ||
| 2114 | |||
| 2115 | A field specification generally has the form @code{([@var{name}] | ||
| 2116 | @var{handler})}. The square braces indicate that @var{name} is | ||
| 2117 | optional. (Don't use names that are symbols meaningful as type | ||
| 2118 | specifications (above) or handler specifications (below), since that | ||
| 2119 | would be ambiguous.) @var{name} can be a symbol or the expression | ||
| 2120 | @code{(eval @var{form})}, in which case @var{form} should evaluate to | ||
| 2121 | a symbol. | ||
| 2122 | |||
| 2123 | @var{handler} describes how to unpack or pack the field and can be one | ||
| 2124 | of the following: | ||
| 2125 | |||
| 2126 | @table @code | ||
| 2127 | @item @var{type} | ||
| 2128 | Unpack/pack this field according to the type specification @var{type}. | ||
| 2129 | |||
| 2130 | @item eval @var{form} | ||
| 2131 | Evaluate @var{form}, a Lisp expression, for side-effect only. If the | ||
| 2132 | field name is specified, the value is bound to that field name. | ||
| 2133 | @var{form} can access and update these dynamically bound variables: | ||
| 2134 | |||
| 2135 | @table @code | ||
| 2136 | @item raw-data | ||
| 2137 | The data as a byte array. | ||
| 2138 | |||
| 2139 | @item pos | ||
| 2140 | Current position of the unpacking or packing operation. | ||
| 2141 | |||
| 2142 | @item struct | ||
| 2143 | Alist. | ||
| 2144 | |||
| 2145 | @item last | ||
| 2146 | Value of the last field processed. | ||
| 2147 | @end table | ||
| 2148 | |||
| 2149 | @item fill @var{len} | ||
| 2150 | Skip @var{len} bytes. In packing, this leaves them unchanged, | ||
| 2151 | which normally means they remain zero. In unpacking, this means | ||
| 2152 | they are ignored. | ||
| 2153 | |||
| 2154 | @item align @var{len} | ||
| 2155 | Skip to the next multiple of @var{len} bytes. | ||
| 2156 | |||
| 2157 | @item struct @var{spec-name} | ||
| 2158 | Process @var{spec-name} as a sub-specification. This describes a | ||
| 2159 | structure nested within another structure. | ||
| 2160 | |||
| 2161 | @item union @var{form} (@var{tag} @var{spec})@dots{} | ||
| 2162 | @c ??? I don't see how one would actually use this. | ||
| 2163 | @c ??? what kind of expression would be useful for @var{form}? | ||
| 2164 | Evaluate @var{form}, a Lisp expression, find the first @var{tag} | ||
| 2165 | that matches it, and process its associated data layout specification | ||
| 2166 | @var{spec}. Matching can occur in one of three ways: | ||
| 2167 | |||
| 2168 | @itemize | ||
| 2169 | @item | ||
| 2170 | If a @var{tag} has the form @code{(eval @var{expr})}, evaluate | ||
| 2171 | @var{expr} with the variable @code{tag} dynamically bound to the value | ||
| 2172 | of @var{form}. A non-@code{nil} result indicates a match. | ||
| 2173 | |||
| 2174 | @item | ||
| 2175 | @var{tag} matches if it is @code{equal} to the value of @var{form}. | ||
| 2176 | |||
| 2177 | @item | ||
| 2178 | @var{tag} matches unconditionally if it is @code{t}. | ||
| 2179 | @end itemize | ||
| 2180 | |||
| 2181 | @item repeat @var{count} @var{field-spec}@dots{} | ||
| 2182 | @var{count} may be an integer, or a list of one element naming a | ||
| 2183 | previous field. For correct operation, each @var{field-spec} must | ||
| 2184 | include a name. | ||
| 2185 | @c ??? What does it MEAN? | ||
| 2186 | @end table | ||
| 2187 | |||
| 2188 | @node Bindat Functions | ||
| 2189 | @subsection Functions to Unpack and Pack Bytes | ||
| 2190 | |||
| 2191 | In the following documentation, @var{spec} refers to a data layout | ||
| 2192 | specification, @code{raw-data} to a byte array, and @var{struct} to an | ||
| 2193 | alist representing unpacked field data. | ||
| 2194 | |||
| 2195 | @defun bindat-unpack spec raw-data &optional pos | ||
| 2196 | This function unpacks data from the byte array @code{raw-data} | ||
| 2197 | according to @var{spec}. Normally this starts unpacking at the | ||
| 2198 | beginning of the byte array, but if @var{pos} is non-@code{nil}, it | ||
| 2199 | specifies a zero-based starting position to use instead. | ||
| 2200 | |||
| 2201 | The value is an alist or nested alist in which each element describes | ||
| 2202 | one unpacked field. | ||
| 2203 | @end defun | ||
| 2204 | |||
| 2205 | @defun bindat-get-field struct &rest name | ||
| 2206 | This function selects a field's data from the nested alist | ||
| 2207 | @var{struct}. Usually @var{struct} was returned by | ||
| 2208 | @code{bindat-unpack}. If @var{name} corresponds to just one argument, | ||
| 2209 | that means to extract a top-level field value. Multiple @var{name} | ||
| 2210 | arguments specify repeated lookup of sub-structures. An integer name | ||
| 2211 | acts as an array index. | ||
| 2212 | |||
| 2213 | For example, if @var{name} is @code{(a b 2 c)}, that means to find | ||
| 2214 | field @code{c} in the second element of subfield @code{b} of field | ||
| 2215 | @code{a}. (This corresponds to @code{struct.a.b[2].c} in C.) | ||
| 2216 | @end defun | ||
| 2217 | |||
| 2218 | @defun bindat-length spec struct | ||
| 2219 | @c ??? I don't understand this at all -- rms | ||
| 2220 | This function returns the length in bytes of @var{struct}, according | ||
| 2221 | to @var{spec}. | ||
| 2222 | @end defun | ||
| 2223 | |||
| 2224 | @defun bindat-pack spec struct &optional raw-data pos | ||
| 2225 | This function returns a byte array packed according to @var{spec} from | ||
| 2226 | the data in the alist @var{struct}. Normally it creates and fills a | ||
| 2227 | new byte array starting at the beginning. However, if @var{raw-data} | ||
| 2228 | is non-@code{nil}, it specifies a pre-allocated string or vector to | ||
| 2229 | pack into. If @var{pos} is non-@code{nil}, it specifies the starting | ||
| 2230 | offset for packing into @code{raw-data}. | ||
| 2231 | |||
| 2232 | @c ??? Isn't this a bug? Shouldn't it always be unibyte? | ||
| 2233 | Note: The result is a multibyte string; use @code{string-make-unibyte} | ||
| 2234 | on it to make it unibyte if necessary. | ||
| 2235 | @end defun | ||
| 2236 | |||
| 2237 | @defun bindat-ip-to-string ip | ||
| 2238 | Convert the Internet address vector @var{ip} to a string in the usual | ||
| 2239 | dotted notation. | ||
| 2240 | |||
| 2241 | @example | ||
| 2242 | (bindat-ip-to-string [127 0 0 1]) | ||
| 2243 | @result{} "127.0.0.1" | ||
| 2244 | @end example | ||
| 2245 | @end defun | ||
| 2246 | |||
| 2247 | @node Bindat Examples | ||
| 2248 | @subsection Examples of Byte Unpacking and Packing | ||
| 2249 | |||
| 2250 | Here is a complete example of byte unpacking and packing: | ||
| 2251 | |||
| 2252 | @lisp | ||
| 2253 | (defvar fcookie-index-spec | ||
| 2254 | '((:version u32) | ||
| 2255 | (:count u32) | ||
| 2256 | (:longest u32) | ||
| 2257 | (:shortest u32) | ||
| 2258 | (:flags u32) | ||
| 2259 | (:delim u8) | ||
| 2260 | (:ignored fill 3) | ||
| 2261 | (:offset repeat (:count) | ||
| 2262 | (:foo u32))) | ||
| 2263 | "Description of a fortune cookie index file's contents.") | ||
| 2264 | |||
| 2265 | (defun fcookie (cookies &optional index) | ||
| 2266 | "Display a random fortune cookie from file COOKIES. | ||
| 2267 | Optional second arg INDEX specifies the associated index | ||
| 2268 | filename, which is by default constructed by appending | ||
| 2269 | \".dat\" to COOKIES. Display cookie text in possibly | ||
| 2270 | new buffer \"*Fortune Cookie: BASENAME*\" where BASENAME | ||
| 2271 | is COOKIES without the directory part." | ||
| 2272 | (interactive "fCookies file: ") | ||
| 2273 | (let* ((info (with-temp-buffer | ||
| 2274 | (insert-file-contents-literally | ||
| 2275 | (or index (concat cookies ".dat"))) | ||
| 2276 | (bindat-unpack fcookie-index-spec | ||
| 2277 | (buffer-string)))) | ||
| 2278 | (sel (random (bindat-get-field info :count))) | ||
| 2279 | (beg (cdar (bindat-get-field info :offset sel))) | ||
| 2280 | (end (or (cdar (bindat-get-field info | ||
| 2281 | :offset (1+ sel))) | ||
| 2282 | (nth 7 (file-attributes cookies))))) | ||
| 2283 | (switch-to-buffer | ||
| 2284 | (get-buffer-create | ||
| 2285 | (format "*Fortune Cookie: %s*" | ||
| 2286 | (file-name-nondirectory cookies)))) | ||
| 2287 | (erase-buffer) | ||
| 2288 | (insert-file-contents-literally | ||
| 2289 | cookies nil beg (- end 3)))) | ||
| 2290 | |||
| 2291 | (defun fcookie-create-index (cookies &optional index delim) | ||
| 2292 | "Scan file COOKIES, and write out its index file. | ||
| 2293 | Optional second arg INDEX specifies the index filename, | ||
| 2294 | which is by default constructed by appending \".dat\" to | ||
| 2295 | COOKIES. Optional third arg DELIM specifies the unibyte | ||
| 2296 | character which, when found on a line of its own in | ||
| 2297 | COOKIES, indicates the border between entries." | ||
| 2298 | (interactive "fCookies file: ") | ||
| 2299 | (setq delim (or delim ?%)) | ||
| 2300 | (let ((delim-line (format "\n%c\n" delim)) | ||
| 2301 | (count 0) | ||
| 2302 | (max 0) | ||
| 2303 | min p q len offsets) | ||
| 2304 | (unless (= 3 (string-bytes delim-line)) | ||
| 2305 | (error "Delimiter cannot be represented in one byte")) | ||
| 2306 | (with-temp-buffer | ||
| 2307 | (insert-file-contents-literally cookies) | ||
| 2308 | (while (and (setq p (point)) | ||
| 2309 | (search-forward delim-line (point-max) t) | ||
| 2310 | (setq len (- (point) 3 p))) | ||
| 2311 | (setq count (1+ count) | ||
| 2312 | max (max max len) | ||
| 2313 | min (min (or min max) len) | ||
| 2314 | offsets (cons (1- p) offsets)))) | ||
| 2315 | (with-temp-buffer | ||
| 2316 | (set-buffer-multibyte nil) | ||
| 2317 | (insert | ||
| 2318 | (string-make-unibyte | ||
| 2319 | (bindat-pack | ||
| 2320 | fcookie-index-spec | ||
| 2321 | `((:version . 2) | ||
| 2322 | (:count . ,count) | ||
| 2323 | (:longest . ,max) | ||
| 2324 | (:shortest . ,min) | ||
| 2325 | (:flags . 0) | ||
| 2326 | (:delim . ,delim) | ||
| 2327 | (:offset . ,(mapcar (lambda (o) | ||
| 2328 | (list (cons :foo o))) | ||
| 2329 | (nreverse offsets))))))) | ||
| 2330 | (let ((coding-system-for-write 'raw-text-unix)) | ||
| 2331 | (write-file (or index (concat cookies ".dat"))))))) | ||
| 2332 | @end lisp | ||
| 2333 | |||
| 2334 | Following is an example of defining and unpacking a complex structure. | ||
| 2335 | Consider the following C structures: | ||
| 2336 | |||
| 2337 | @example | ||
| 2338 | struct header @{ | ||
| 2339 | unsigned long dest_ip; | ||
| 2340 | unsigned long src_ip; | ||
| 2341 | unsigned short dest_port; | ||
| 2342 | unsigned short src_port; | ||
| 2343 | @}; | ||
| 2344 | |||
| 2345 | struct data @{ | ||
| 2346 | unsigned char type; | ||
| 2347 | unsigned char opcode; | ||
| 2348 | unsigned long length; /* In little endian order */ | ||
| 2349 | unsigned char id[8]; /* null-terminated string */ | ||
| 2350 | unsigned char data[/* (length + 3) & ~3 */]; | ||
| 2351 | @}; | ||
| 2352 | |||
| 2353 | struct packet @{ | ||
| 2354 | struct header header; | ||
| 2355 | unsigned char items; | ||
| 2356 | unsigned char filler[3]; | ||
| 2357 | struct data item[/* items */]; | ||
| 2358 | |||
| 2359 | @}; | ||
| 2360 | @end example | ||
| 2361 | |||
| 2362 | The corresponding data layout specification: | ||
| 2363 | |||
| 2364 | @lisp | ||
| 2365 | (setq header-spec | ||
| 2366 | '((dest-ip ip) | ||
| 2367 | (src-ip ip) | ||
| 2368 | (dest-port u16) | ||
| 2369 | (src-port u16))) | ||
| 2370 | |||
| 2371 | (setq data-spec | ||
| 2372 | '((type u8) | ||
| 2373 | (opcode u8) | ||
| 2374 | (length u16r) ;; little endian order | ||
| 2375 | (id strz 8) | ||
| 2376 | (data vec (length)) | ||
| 2377 | (align 4))) | ||
| 2378 | |||
| 2379 | (setq packet-spec | ||
| 2380 | '((header struct header-spec) | ||
| 2381 | (items u8) | ||
| 2382 | (fill 3) | ||
| 2383 | (item repeat (items) | ||
| 2384 | (struct data-spec)))) | ||
| 2385 | @end lisp | ||
| 2386 | |||
| 2387 | A binary data representation: | ||
| 2388 | |||
| 2389 | @lisp | ||
| 2390 | (setq binary-data | ||
| 2391 | [ 192 168 1 100 192 168 1 101 01 28 21 32 2 0 0 0 | ||
| 2392 | 2 3 5 0 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0 | ||
| 2393 | 1 4 7 0 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ]) | ||
| 2394 | @end lisp | ||
| 2395 | |||
| 2396 | The corresponding decoded structure: | ||
| 2397 | |||
| 2398 | @lisp | ||
| 2399 | (setq decoded (bindat-unpack packet-spec binary-data)) | ||
| 2400 | @result{} | ||
| 2401 | ((header | ||
| 2402 | (dest-ip . [192 168 1 100]) | ||
| 2403 | (src-ip . [192 168 1 101]) | ||
| 2404 | (dest-port . 284) | ||
| 2405 | (src-port . 5408)) | ||
| 2406 | (items . 2) | ||
| 2407 | (item ((data . [1 2 3 4 5]) | ||
| 2408 | (id . "ABCDEF") | ||
| 2409 | (length . 5) | ||
| 2410 | (opcode . 3) | ||
| 2411 | (type . 2)) | ||
| 2412 | ((data . [6 7 8 9 10 11 12]) | ||
| 2413 | (id . "BCDEFG") | ||
| 2414 | (length . 7) | ||
| 2415 | (opcode . 4) | ||
| 2416 | (type . 1)))) | ||
| 2417 | @end lisp | ||
| 2418 | |||
| 2419 | Fetching data from this structure: | ||
| 2420 | |||
| 2421 | @lisp | ||
| 2422 | (bindat-get-field decoded 'item 1 'id) | ||
| 2423 | @result{} "BCDEFG" | ||
| 2424 | @end lisp | ||
| 2425 | |||
| 2018 | @ignore | 2426 | @ignore |
| 2019 | arch-tag: ba9da253-e65f-4e7f-b727-08fba0a1df7a | 2427 | arch-tag: ba9da253-e65f-4e7f-b727-08fba0a1df7a |
| 2020 | @end ignore | 2428 | @end ignore |
| 2021 | |||