资源说明:Text Generation Language --- A very terse language intended for one- or few-time ad-hoc text generation.
Installing TGL Dependencies: You only need a C compiler and the standard UNIX utilities to build TGL. TGL has commands for running Perl and Tcl; you will obviously need those programs in order to use those commands, but they are otherwise not required for anything. Building: You can compile TGL by running ./configure make Installing: Just run make install or sudo make install Integrating into your favourite editor is generally more a question of your user configuration than being installed, so see the files under doc/examples for information on integrating with various editors. Uninstalling: Like installing: make uninstall or sudo make uninstall Manual page follows: TGL(1) BSD General Commands Manual TGL(1) NAME tgl — Run the Text Generation Language interpreter SYNOPSIS tgl [-h] [-p] [-c context] [-l library] [-r file] DESCRIPTION Runs the Text Generation Language interpreter on the script read from standard input. tgl supports the following options: -h Show usage and exit. -p Search for prefix payload data. -c context Specify the current context (for conditional execution). -l library Use the file specified by library (instead of ~/.tgl) for the user library. -r file Use file (instead of ~/.tgl_registers) for register persistence. When Tgl starts up, it first restores registers from the register persis‐ tence file (by default, ~/.tgl_registers), then executes the user library if it exists (by default, ~/.tgl). Any errors in either of these steps are reported but otherwise ignored. The script to execute is then read from standard input, until EOF is reached. The script is then executed; if any error occurs, execution is aborted. If no errors are encountered, the final state of the registers is written back to the register persistence file. EXIT STATUS tgl exits with status 0 on success. An exit status of 1 indicates failure due to an error in the input program. Stati 253--255 indicate failures due to external conditions. BASIC CONCEPTS VALUES Every value in Tgl is a string. A string is simply a sequence of arbi‐ trary 8-bit bytes of arbitrary length. Some commands will interpret the strings as integers or booleans. An integer is a string beginning with a "+" or "-", followed by any number of base-10 digits. Base-16 (hexadeci‐ mal) may be specified by prefixing the digits with "0x", base-8 (octal) by "0o", or base-2 (binary) by "0b". A boolean string is false if it is the empty string or if it is a valid representation of numeric zero. Any other string is considered true. STACK The stack is the primary method of passing data to and from commands. With few exceptions, all commands only pop values from and push values to the top of the stack. There is no limit on stack height, other than available memory. It is an error to try to pop from the stack when it is empty. REGISTERS Tgl provides the programmer with exactly 256 registers, each correspond‐ ing to a single byte value. Each register contains one string, and also stores its time of last access. Other than the history system, commands do not use registers except when doing so to present functionality to the user. Registers are all initialised to empty strings. When Tgl exits success‐ fully, it will write the state of all registers to the register persis‐ tence file. This file is read back in the next time Tgl runs, so regis‐ ters will preserve their values across invocations of Tgl. Registers 0x00..0x1F (ie, the byte values) are used to store command his‐ tory, where register 0 is the most recently run command sequence. When TGL runs successfully and history was not suppressed, and the command sequence was not "hX", the command sequence is added to the history by moving 0x00..0x1E each one register up, then inserted to register 0x00. SECONDARY ARGUMENTS Some commands take optional parameters via a secondary argument system. There are four secondary argument slots, called U0..U3. Unlike registers, they cannot be accessed directly, and may be null. Any command which takes secondary arguments nullifies all four slots after execution. There is also the secondary index, UX, which indicates which slot is used next. It starts at zero, and is incremented whenever a secondary argument is set. It is zeroed when a secondary-argument-using command completes exe‐ cution. A secondary argument is considered "set" when UX has advanced beyond its own index. It is considered "provided" when it is set and non-null. Commands which use secondary arguments indicate such usage similar to the example below: Secondary: [value = default] [provided] (set?) Brackets indicate that the argument is considered if provided; paranthe‐ ses, if set. Items of the format value=default indicate a property which has the given default if the argument is not provided, but which takes the value of any argument which is provided. Items of the format prop‐ erty? indicate booleans which are false unless the argument is provided or set (depending on whether brackets or parentheses are used), regard‐ less of the argument's value. Any argument not noted is silently ignored. The u (secondary-argument) command is used to set secondary arguments. What it does depends on the following character: % Pop a value from the main stack and use it to provide the next argument space Set the next argument to null digit Evaluate the following digits (using the number command) and use the result to provide the next argument - + Same as digit . Provides an integer corresponding to the current stack height as the next argument. other Create a one-character string with the given character and use it to provide the next argument PAYLOAD DATA In some cases, it is desirable to take data from a structured source, either embedded in the script itself, or extracted from an external source. The , command provides functionality to access and manipulate this payload data. Most commonly, one includes payload data within the script itself. Usu‐ ally, payload data starts after the text ",$", though the delimiter can be changed. By passing the -p (or --prefix-payload) flag, it is also pos‐ sible to include a payload at the beginning of input. In this case, code is considered to start after the first "|" (though initial whitespace (for the ` character within strings) still counts within the payload). Multiple pipes can be used to include the "|" within the payload; the first occurance that has the greatest number of pipes is used to separate the payload and the code. The first occurrance of a payload-data command which requires access to the payload will search for the start-of-payload delimiter (default ",$") in the code if no payload is already present. COMMANDS All "true commands" in TGL are represented by a single character. When‐ ever the interpreter must execute a command, it looks at the character at the interpreter's current instruction pointer, and runs the associated command. All whitespace characters are implicitly considered no-op com‐ mands. If the command completes successfully, the instruction pointer is incremented. Builtin commands have access to all interpreter state, including the code and instruction pointer itself. Many commands will move the instruction pointer to effect control and quoting mechanisms. See the description for each command. CONTEXT TGL is run with a context (the empty string if not given) and maintains whether the context is active. The context is typically specified as a filename. Some commands only have effect if the context is active, allow‐ ing for language- or project-specific functionality. CATEGORICAL COMMAND REFERENCE STACK x (swap: a{depth} b -> b a{depth}, or b a{-depth} -> a{-depth} b) Secondary: [depth = 1] The top two items on the stack are swapped. With a secondary argument, this rolls the top element under that many items if positive, or moves an item at that depth to the top if negative. : (dupe: item -> item{times+1}) Secondary: [times = 1] Pops an item from the stack, then pushes (times+1) copies of it onto the stack. ; (drop: item{times} -> ()) Secondary: [times = 1] Pops (times) items from the stack and discards them. STRINGS c (concat: a b -> ab) Pops two strings from the stack, concatenates them, and pushes the result. C (char-at: string index -> char) Pops a string and an index, and pushes the character within the string at that index. The first character is at index 0. Negative indices are relative to the end of the string. l (length: string -> length) Pops a string from the stack and pushes its length, in bytes. m (map: string {from to}{n} n -> result, or string ... -> result) Secondary: [stack-position-of-string = null] Translates each occurrance of from to the corresponding to in string such that no mappings interact. The number of mappings must be specified explicitly on the stack if no secondary argu‐ ment is given; if one is given, it should be a "u." command after string but before the first mapping. s (substr: string from to -> length) Pops a string and two indices, evaluated the same was as in char- at, and pushes the portion of the string between from, inclusive, to to, exclusive. S (suffix: string from -> length) Same as substr, but assumes that to is the length of the string. y (empty-string: () -> "") Pushes the empty string onto the stack. " ... " (string: ??? -> string) Pushes the characters between the double-quotes as a string onto the stack. The following characters are interpreted specially: \ Evaluates the \ command at that point and splices the result into the string. Characters continue to be read after the point where \ left off. $ Interprets the following character as a register name; the value of this register is spliced into the string at that point. % Pops a value from the stack and splices it into the string at that point. ` Inserts the string of whitespace characters that were present before the first non-whitespace character in the primary input. ' C (char: () -> string) Pushes a single-character string, whose contents is the character following the command, to the stack. Note that since TGL is not Unicode-aware, this more strictly pushes a single byte. For example, the code 'ß will not push a string containing an Eszett, but rather (assuming UTF-8) a string containing the byte 0xC3; the interpreter will then try to execute command 0x9F. (...) (code: () -> string) Pushes the string between the parentheses verbatim. The parenthe‐ ses must be balanced; for example, the code (foo (bar) baz) pushes the string foo (bar) baz . (print: string -> ()) Pops a string from the stack and writes it verbatim to standard output. \ (escape: () -> string or () -> ()) Pushes a single character as indicated by the following charac‐ ter(s). Control characters: \a BEL \b BS \e ESC \f FF \n LF \r CR \t HT \v VT \x## The byte represented by the hexadecimal integer ##. The following result in the character being escaped: \" \\ \$ \% \` \' The following result in nothing (not even a string is pushed); they may be used for manual balancing of parentheses as required by some commands. \( \) \[ \] \{ \} \< \> = (equal: a b -> (a==b)) Pops two strings and pushes a boolean indicating whether they are exactly equal. ! (not-equal: a b -> (a!=b)) Pops two strings and pushes a boolean indicating whether they are not exactly equal. { (string-less: a b -> (a (a>b)) Pops two strings and pushes a boolean indicating whether the left is greater than (ASCIIbetically) the right. MATH #/digit ... (number: () -> integer) Reads an integer and pushes it onto the stack, stopping on the first non-digit. Any digit (0..9) is bound to this command; the # command also allows a leading sign before the number itself. ? (rand: () -> integer) Pushes a random integer between 0 and 65535, inclusive, onto the stack. + (add: a b -> (a+b)) Pops two stack elements, interprets them as integers, and pushes their sum onto the stack. - (sub: a b -> (a-b)) Pops two stack elements, interprets them as integers, and pushes their difference onto the stack. * (mul: a b -> (a*b)) Pops two stack elements, interprets them as integers, and pushes their product onto the stack. / (div: a b -> (a/b)) Pops two stack elements, interprets them as integers, and pushes their quotient onto the stack. % (mod: a b -> (a%b)) Pops two stack elements, interprets them as integers, and pushes their remainder onto the stack. < (less: a b -> (a (greater: a b -> (a>b)) Pops two integers and pushes a boolean indicating whether the left is greater than the left. & (and: a b -> (a&&b)) Pops two booleans and pushes the result of logical AND. Note that due to the nature of TGL this is not, and cannot be, short-cir‐ cuiting. | (or: a b -> (a||b)) Pops two booleans and pushes the result of logical OR. Note that due to the nature of TGL this is not, and cannot be, short-cir‐ cuiting. ^ (xor: a b -> (a^b)) Pops two booleans and pushes the result of logical XOR. ~ (not: a -> !a) Pops a boolean and pushes its negation. REGISTERS a (auto-write: value -> ()) Pops a string and stores it into a register with an alphanumeric name. The register chosen is the one with the earliest date of last use. After writing the register, prints a string of the for‐ mat `%s: %c\n indicating the value stored and the register it was stored in. (The first character is a literal grave quote, while the last one is a linefeed.) p (stash: () -> ()) Pushes all registers onto a stack independent of the primary stack. P (retrieve: () -> ()) Restores all registers as preserved by stash, removing that entry. r R (read: () -> value) Pushes the contents of register R onto the stack. R R (write: value -> ()) Pops value from the stack and stores it into register R. u X (secondary-argument: () -> () or value -> ()) The effect of this command depends on X. See SECONDARY ARGUMENTS above. z (stash-retrieve: code -> guarded-code) Pops code and places p...P guards around it, so that no changes to registers occur due to execution of code (assuming it contains no ",$"). PAYLOAD All payload commands are prefixed with ",". ,$ (payload-start: () -> ()) Immediately moves the instruction pointer to the end of the cur‐ rent code, effectively stopping processing. ,c (payload-curr: () -> elt) Pushes the string corresponding to the first element of the cur‐ rent payload data onto the stack. ,, (payload-next: () -> ()) Secondary: [count = 1] Deletes the first count elements from the current payload data. ,; (payload-next-kv: () -> ()) Secondary: [count = 1] Deletes the first count pairs of elements from the current pay‐ load data. ,. (payload-print: () -> ()) Secondary: [count = 1] Prints the first count elements of the payload data, separated by the current output-v-delimiter, then deletes them. A count of zero indicates all elements. ,: (payload-print-kv: () -> ()) Secondary: [count = 1] Prints the first count key-value pairs of the payload data. Each key and value is separated by the current output-kv-delimiter, and each pair is separated by the current output-kvs-delimiter. A count of zero indicates all pairs. ,r (payload-read: () -> payload) Pushes the string representation of the current payload data onto the stack. ,R (payload-write: payload -> ()) Sets the current payload data to the string popped from the stack. ,x (payload-recurse: payload code -> ()) Saves all current payload state, then sets the payload to payload and executes code. After execution, payload state (including delimiters and such) is reverted to what is was before execution of this command. ,h (payload-length-bytes: () -> byte-count) Pushes an integer indicating how many bytes remain in the current payload data. Returns zero if and only if no elements remain in the current payload. (Thus the mnemonic Has-more) ,e (payload-each: ??? body -> ???) Secondary: [reg = "p"] For each value in the current payload, set reg to that value and execute body. This does not modify the current payload data. The result of the payload data having been altered after body exits is undefined. ,E (payload-each-kv: ??? body -> ???) Secondary: [key-reg = "k"] [val-reg = "v"] For each key-value pair in the current payload, set key-reg to the key and val-reg to the value, then execute body. This does not modify the current payload data. The result of the payload data having been altered after body exits is undefined. ,i (payload-datum-at-index: index -> value) Pushes the payload element at index, where 0 is the index of the first element. This operation requires a linear scan of the pay‐ load data. ,I (payload-num-indices: () -> count) Counts the number of elements in the current payload data and pushes the result. This operation requires a linear scan of the payload data. ,k (payload-datum-at-key: key -> value) Pushes the first payload value element which follows the given key. This opretation requires a linear scan of the payload data. ,/ VV (payload-set-property: value -> ()) Sets the property VV to value. Properties are: ps (payload-start, default ",$") The delimiter that separates code from payload in the main body. vd (value-delimiter, default "ws" (see ",s")) The delimiter that separates elements in the payload data. ov (output-v-delimiter, default ", ") The string to separate con‐ tiguous normal values on output. ok (output-kv-delimiter, default ", ") The string to separate keys from values on output. os (output-kvs-delimiter, default "\n") The string to separate key-value pairs on output. b( b[ b{ b< (balance-paren) Set to any boolean. If true, delim‐ iters are ignored when between yet-unbalanced pairs of the given type of parenthesis character. If false, the characters are treated normally. Default is true for ([{, false for <. t( t[ t{ t< (trim-paren) Set to any boolean. If true, up to one single matching pair of the given parenthesis type is trimmed from a value before extraction. This is performed after whitespace trimming, and no further trimming is done after this step. Default is true for ([{, false for <. ts (trim-space, default true) Set to any boolean. If true, extra‐ neous spaces around values are trimmed when being extracted. ,? VV (payload-get-property: () -> value) Pushes the current value of property VV. See ",/". ,s (payload-space-delimited: () -> ()) Sets payload to be delimited by whitespace of any kind, combina‐ tion, and abount. Resets balance and trim properties to defaults. If this mode is in use when payload is first extracted (or with any command which alters the payload), leading space in the pay‐ load is skipped. This is indicated in delimiter properties with the special string "ws". ,0 (payload-nul-delimited: () -> ()) Sets payload to be delimited by NUL characters, and sets all bal‐ ance and trim properties to false. ,l (payload-line-delimited: () -> ()) Sets the following strings: "\n" "\r" "\r\n" as the value delimiter, and sets all paren-related balancing and trimming to false. Space trimming is set to true. ,! (payload-from-code: () -> ()) Extracts the payload from the suffix from the top-level primary code, using the current payload-start delimiter. This is automat‐ ically done if no payload has ever been extracted when a command that accesses the payload data is run. ,f (payload-from-file: filename -> ()) Reads the entire contents of filename and uses it as payload data. ,F (payload-from-glob: glob -> ()) Accumulates all filenames matching glob and stores them into the payload data, NUL-delimited. Implicitly executes ",0" after. CONTROL STRUCTURES d (defun: name body -> ()) Defines the command of the given name, which may be standard (one character long) or long (more than one character long). It is an error if it already exists. After execution of this command, the new command can be invoked in the normal manner (directly if a standard name, or with Q... if it is long). D (defun-contextual: name body -> ()) Like defun except that nothing happens if the current context is not active. e (each: ??? string body -> ???) Secondary: [reg = "c"] For each character in string, set reg to a string with that char‐ acter as its only content, then execute body. f (for: ??? to body -> ???) Secondary: [from = 0] [reg = "i"] [increment = +1 or -1] Set reg to from. Execute body, then add increment to reg. If reg has not moved to the other side of to from whence it started and is not equal to to, the command repeats. If increment is not given, it defaults to +1 if to is greater than from, or -1 other‐ wise. i (if: ??? condition then else -> ???) If condition is a true boolean, executes then; otherwise, exe‐ cutes else. Other than the three arguments given, the effect on the interpreter is entirely dependent on the code executed. Note: condition is a value, not code to execute. The code (1 2=)('y)('n)i. will print "y" since "1 2=" is a true string. For the desired effect, the code should read 1 2=('y)('n)i. I (if-short: ??? condition then -> ???) The same as if except that it does nothing if condition is false. Q ... (long-command: ??? -> ???) Reads characters from the code until end of input or whitespace is encountered. These characters (excluding the leading "Q") con‐ stitute a long command name. The command corresponding to this name is executed. The way the interpreter is affected depends entirely on what the command does. v (save-code: name code -> ()) Creates a defun using the given name and code, executes it (the defun, not the code), and appends the definition to the user library if successful. V t (save-code-contextual: name code -> ()) Like save-code, but also restricts the definition to the context indicated by t. If t is "s", the whole context must match; if it is "e", only the extension must match. No other values of t are permitted. w (while: ??? condition body -> ???) Executes condition and pops a value from the stack. If it is false, the command stops. Otherwise, body is executed and the command repeats. Notice that unlike if, condition is code to evaluate on each iteration, instead of a value by itself. W (while-short: ??? body -> ???) Executes code and pops a value from the stack. If it is true, the command repeats. X (eval: ??? code -> ???) Pops a string from the stack and evaluates it as TGL code. The way the interpreter is affected depends entirely on what the code does. CONTEXT All context commands are prefixed with @. Any occurrance of "..." in these commands indicates that a string is read until the next whitespace character. The string "matches" if the glob defined by the string which was read (see fnmatch(3)) matches the current context (as with -c ). @= ... (context-set: () -> ()) The context is made active if matches, inactive if does not match. @! ... (context-set-not: () -> ()) The context is made inactive if matches, active if does not match. @& ... (context-and: () -> ()) The context is made inactive if does not match. @| ... (context-or: () -> ()) The context is made active if matches. @^ ... (context-and-not: () -> ()) The context is made inactive if matches. @| ... (context-or-not: () -> ()) The context is made active if does not match. @? (context-active: () -> active-state) Pushes a boolean indicating whether the context is active. @s (context-query: () -> context) Pushes the current context itself. @e (context-extension: () -> extension) Pushes the filename extension of the context, including the leading dot, if present; otherwise, an empty string. HISTORY/LIBRARY h (history-access: () -> entry) Secondary: [off = 0] Accesses the item in history at (off+implicit). implicit begins at 0 and is incremented every time history-access is invoked. H (suppress-history: () -> ()) Prevents the current code from being added to the history. EXTERNAL COMMANDS b (shell-script: input script -> output) Secondary: [status-reg = null] Executes ".Ar $SHELL -c script " using input as its standard input. Output is accumulated and pushed onto the stack when the command completes. If status-reg is specified, the exit code of the child process is stored as an integer to that register. Oth‐ erwise, it is an error if the child exits with a non-zero status. In any case, an abnormally terminated process (eg, one that was killed) results in an error. B (shell-command: input args{n} n -> output, or input ... -> output) Secondary: [stack-depth-of-input = null] [status-reg = null] Execute the given shell command, the arguments pushed in the order they will be used. The first argument is the command to run. No additional processing is performed on the arguments given: They are passed to the program verbatim (this means, for example, that no quoting is necessary). Example: yu."echo" "hello" "world"B. --> hello world Standard input is provided by input; standard output is accumu‐ lated into output and pushed when the command completes. If status-reg is specified, the exit code of the child process is stored as an integer to that register. Otherwise, it is an error if the child exits with a non-zero status. In any case, an abnor‐ mally terminated process (eg, one that was killed) results in an error. j ... (sed: input -> output, or input script -> output) Executes "sed -r" on the given input, pushing the output onto the stack. The script is normally read in after the command name itself, and follows this pseudo-extended-regex: (${STATEMENT};\s*)*${STATEMENT} where ${STATEMENT} = [a-zA-Z](.)[^\1]*\1[^\1]*\1[a-zA-Z]* If no script follows the command, it is instead popped from the stack. The environment variable TGL_SED can be used to override the name of the sed command. J (perl: input script -> output) INvokes "perl -E" with the given script and standard input. The environment variable TGL_PERL can be set to override the location of the perl executable. t (tcl: input script -> output) Invokes "tclsh" with the given input and script, and pushes the output onto the stack. The executable name can be overridden with the environment variable TGL_TCL. COMMAND INDEX BY INVOCATION a auto-write b shell-script B shell-command c concat C char-at d defun D defun-contextual e each f for h history-access H suppress-history i if I if-short j sed J perl l length m map Q long-command p stash P retrieve r read R write s substr S suffix t tcl u secondary-argument v save-code V save-code-contextual w while W while-short x swap X eval y empty-string z stash-retrieve ! not-equal " string # number % mod & and ' char ( code * mul + add ,0 payload-nul-delimited ,c payload-curr ,e payload-each ,E payload-each-kv ,f payload-from-file ,F payload-from-glob ,h payload-length-bytes ,i payload-datum-at-index ,k payload-datum-at-key ,l payload-line-delimited ,l payload-num-indices ,r payload-read ,R payload-write ,s payload-space-delimited ,x payload-recurse ,! payload-from-code ,$ payload-start ,, payload-next ,. payload-print ,/ payload-set-property ,: payload-print-kv ,; payload-next-kv ,? payload-get-property - sub . print / div digit number : dupe ; drop < less = equal > greater ? rand @= context-set @! context-set-not @& context-and @| context-or @^ context-and-not @v context-or-not @? context-active @s context-query @e context-extension \ escape ^ xor { string-less | or } string-greater ~ not BY NAME add + and & auto-write a char ' char-at C code ( concat c context-active @? context-and @& context-and-not @^ context-extension @e context-or @| context-or-not @v context-query @s context-set @= context-set-not @! defun d defun-contextual D div / drop ; dupe : each e escape \ for f empty-string y equal ! eval X greater > history h if i if-short I length l less < long-command Q map m mul * not ~ not-equal ! number Any of: #0123456789 or | payload-curr ,c payload-datum-at-index ,i payload-datum-at-key ,k payload-each ,e payload-each-kv ,E payload-from-code ,! payload-from-file ,f payload-from-glob ,F payload-get-property ,? payload-length-bytes ,h payload-line-delimited ,l payload-next ,, payload-next-kv ,; payload-nul-delimited ,0 payload-num-indices ,I payload-print ,. payload-print-kv ,: payload-read ,r payload-recurse ,x payload-set-property ,/ payload-space-delimited ,s payload-start ,$ payload-write ,R perl J print . rand ? read r retrieve P save-code v save-code-contextual V secondary-argument u sed j shell-command B shell-script b stash p stash-retrieve z string " string-greater } string-less { sub - substr s suffix S suppress-history H swap x tcl t while w while-short W write R xor ^ ENVIRONMENT SHELL The command to use to run shell commands. TGL_SED The command to use instead of "sed" for the sed builtin. TGL_PERL The command to use instead of "perl" for the perl builtin. TGL_TCL The command to use instead of "tclsh" for the tcl builtin. FILES ~/.tgl The default location of the user library. This is a TGL script which is automatically read when TGL starts, and any commands affecting the library write to it. It can be overridden with the -l parameter. ~/.tgl_registers The default location of the register persistence file. This is a binary file used to save and restore registers between invoca‐ tions of TGL. EXAMPLES HELLO WORLD "Hello, world!". 99 BOTTLES OF BEER 99Rc"bottles"RBrcRC(rc#-1>)( "$C $B of beer on the wall\n$C $B of beer\n". rc1-Rc rc1=("bottle")("bottles")iRBrc0=("No more")(rc)iRC rc#-1=( "Go to the store, buy some more\n99 bottles of beer on the wall\n" )( "Take one down, pass it around\n$C $B of beer on the wall\n" )i.)w CASE STATEMENTS, HISTORY Quickly generate case statements for each digit: 10("`case '$i':\n".)f Save the previous to a language-specific macro: "nc"hzVe Resusing the new macro: Qnc CONTEXT Creating a macro to place strings into C-strings (quoting and escaping): @=*.h @|*.c "cq" (u.\\(\\)\n(\n)\r(\r)\t(\t)\"(\")\e(\e)\f(\f)\v(\v)m"\"%\"") D EXTERNAL COMMANDS, ABUSE The following program will produce a graph (using dot) in deps.png which shows an include dependency graph of your C project. "digraph{rankdir=LR\n"Rgy"find src -name '*.[hc]'"b,R(rp js:.*/::g Rb("grep '$b\"' '$o'"yxusb;rs~(rg "\"$o\" -> \"$p\"\n"cRg)I)uo,e),erg"}\n"c "dot -odeps.png -Tpng"b BSD 16 June 2012 BSD
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。