toybox/www/design.html
<<
>>
Prefs
   1<html><head><title>The design of toybox</title></head>
   2<!--#include file="header.html" -->
   3
   4<a name="goals"><b><h2><a href="#goals">Design goals</a></h2></b>
   5
   6<p>Toybox should be simple, small, fast, and full featured. In that order.</p>
   7
   8<p>When these goals need to be balanced off against each other, keeping the code
   9as simple as it can be to do what it does is the most important (and hardest)
  10goal. Then keeping it small is slightly more important than making it fast.
  11Features are the reason we write code in the first place but this has all
  12been implemented before so if we can't do a better job why bother?</p>
  13
  14<p>It should be possible to get 80% of the way to each goal
  15before they really start to fight. Here they are in reverse order
  16of importance:</p>
  17
  18<b><h3>Features</h3></b>
  19
  20<p>These days toybox is the command line of Android, so anything they android
  21guys say to do gets at the very least closely listened to.</p>
  22
  23<p>Toybox should provide the command line utilities of a build
  24environment capable of recompiling itself under itself from source code.
  25This minimal build system conceptually consists of 4 parts: toybox,
  26a C library, a compiler, and a kernel. Toybox needs to provide all the
  27commands (with all the behavior) necessary to run the configure/make/install
  28of each package and boot the resulting system into a usable state.</p>
  29
  30<p>In addition, it should be possible to bootstrap up to arbitrary complexity
  31under the result by compiling and installing additional packages into this
  32minimal system, as measured by building both Linux From Scratch and the
  33Android Open Source Project under the result. Any "circular dependencies"
  34should be solved by toybox including the missing dependencies itself
  35(see "Shared Libraries" below).</p>
  36
  37<p>Finally, toybox may provide some "convenience" utilties
  38like top and vi that aren't necessarily used in a build but which turn
  39the minimal build environment into a minimal development environment
  40(supporting edit/compile/test cycles in a text console), configure
  41network infrastructure for communication with other systems (in a build
  42cluster), and so on.</p>
  43
  44<p>The hard part is deciding what NOT to include.
  45A project without boundaries will bloat itself
  46to death. One of the hardest but most important things a project must
  47do is draw a line and say "no, this is somebody else's problem, not
  48something we should do."
  49Some things are simply outside the scope of the project: even though
  50posix defines commands for compiling and linking, we're not going to include
  51a compiler or linker (and support for a potentially infinite number of hardware
  52targets). And until somebody comes up with a ~30k ssh implementation (with
  53a crypto algorithm that won't need replacing every 5 years), we're
  54going to point you at dropbear or bearssl.</p>
  55
  56<p>The <a href=roadmap.html>roadmap</a> has the list of features we're
  57trying to implement, and the reasons why we decided to include those
  58features. After the 1.0 release some of that material may get moved here,
  59but for now it needs its own page. The <a href=status.html>status</a>
  60page shows the project's progress against the roadmap.</p>
  61
  62<p>There are potential features (such as a screen/tmux implementation)
  63that might be worth adding after 1.0, in part because they could share
  64infrastructure with things like "less" and "vi" so might be less work for
  65us to do than for an external from scratch implementation. But for now, major
  66new features outside posix, android's existing commands, and the needs of
  67development systems, are a distraction from the 1.0 release.</p>
  68
  69<b><h3>Speed</h3></b>
  70
  71<p>It's easy to say lots about optimizing for speed (which is why this section
  72is so long), but at the same time it's the optimization we care the least about.
  73The essence of speed is being as efficient as possible, which means doing as
  74little work as possible.  A design that's small and simple gets you 90% of the
  75way there, and most of the rest is either fine-tuning or more trouble than
  76it's worth (and often actually counterproductive).  Still, here's some
  77advice:</p>
  78
  79<p>First, understand the darn problem you're trying to solve.  You'd think
  80I wouldn't have to say this, but I do.  Trying to find a faster sorting
  81algorithm is no substitute for figuring out a way to skip the sorting step
  82entirely.  The fastest way to do anything is not to have to do it at all,
  83and _all_ optimization boils down to avoiding unnecessary work.</p>
  84
  85<p>Speed is easy to measure; there are dozens of profiling tools for Linux
  86(although personally I find the "time" command a good starting place).
  87Don't waste too much time trying to optimize something you can't measure,
  88and there's no much point speeding up things you don't spend much time doing
  89anyway.</p>
  90
  91<p>Understand the difference between throughput and latency.  Faster
  92processors improve throughput, but don't always do much for latency.
  93After 30 years of Moore's Law, most of the remaining problems are latency,
  94not throughput.  (There are of course a few exceptions, like data compression
  95code, encryption, rsync...)  Worry about throughput inside long-running
  96loops, and worry about latency everywhere else.  (And don't worry too much
  97about avoiding system calls or function calls or anything else in the name
  98of speed unless you are in the middle of a tight loop that's you've already
  99proven isn't running fast enough.)</p>
 100
 101<p>"Locality of reference" is generally nice, in all sorts of contexts.
 102It's obvious that waiting for disk access is 1000x slower than doing stuff in
 103RAM (and making the disk seek is 10x slower than sequential reads/writes),
 104but it's just as true that a loop which stays in L1 cache is many times faster
 105than a loop that has to wait for a DRAM fetch on each iteration.  Don't worry
 106about whether "&" is faster than "%" until your executable loop stays in L1
 107cache and the data access is fetching cache lines intelligently.  (To
 108understand DRAM, L1, and L2 cache, read Hannibal's marvelous ram guide at Ars
 109Technica:
 110<a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part1-2.html>part one</a>,
 111<a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part2-1.html>part two</a>,
 112<a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part3-1.html>part three</a>,
 113plus this
 114<a href=http://arstechnica.com/articles/paedia/cpu/caching.ars/1>article on
 115cacheing</a>, and this one on
 116<a href=http://arstechnica.com/articles/paedia/cpu/bandwidth-latency.ars>bandwidth
 117and latency</a>.
 118And there's <a href=http://arstechnica.com/paedia/index.html>more where that came from</a>.)
 119Running out of L1 cache can execute one instruction per clock cycle, going
 120to L2 cache costs a dozen or so clock cycles, and waiting for a worst case dram
 121fetch (round trip latency with a bank switch) can cost thousands of
 122clock cycles.  (Historically, this disparity has gotten worse with time,
 123just like the speed hit for swapping to disk.  These days, a _big_ L1 cache
 124is 128k and a big L2 cache is a couple of megabytes.  A cheap low-power
 125embedded processor may have 8k of L1 cache and no L2.)</p>
 126
 127<p>Learn how <a href=http://nommu.org/memory-faq.txt>virtual memory and
 128memory managment units work</a>.  Don't touch
 129memory you don't have to.  Even just reading memory evicts stuff from L1 and L2
 130cache, which may have to be read back in later.  Writing memory can force the
 131operating system to break copy-on-write, which allocates more memory.  (The
 132memory returned by malloc() is only a virtual allocation, filled with lots of
 133copy-on-write mappings of the zero page.  Actual physical pages get allocated
 134when the copy-on-write gets broken by writing to the virtual page.  This
 135is why checking the return value of malloc() isn't very useful anymore, it
 136only detects running out of virtual memory, not physical memory.  Unless
 137you're using a <a href=http://nommu.org>NOMMU system</a>, where all bets are off.)</p>
 138
 139<p>Don't think that just because you don't have a swap file the system can't
 140start swap thrashing: any file backed page (ala mmap) can be evicted, and
 141there's a reason all running programs require an executable file (they're
 142mmaped, and can be flushed back to disk when memory is short).  And long
 143before that, disk cache gets reclaimed and has to be read back in.  When the
 144operating system really can't free up any more pages it triggers the out of
 145memory killer to free up pages by killing processes (the alternative is the
 146entire OS freezing solid).  Modern operating systems seldom run out of
 147memory gracefully.</p>
 148
 149<p>Also, it's better to be simple than clever.  Many people think that mmap()
 150is faster than read() because it avoids a copy, but twiddling with the memory
 151management is itself slow, and can cause unnecessary CPU cache flushes.  And
 152if a read faults in dozens of pages sequentially, but your mmap iterates
 153backwards through a file (causing lots of seeks, each of which your program
 154blocks waiting for), the read can be many times faster.  On the other hand, the
 155mmap can sometimes use less memory, since the memory provided by mmap
 156comes from the page cache (allocated anyway), and it can be faster if you're
 157doing a lot of different updates to the same area.  The moral?  Measure, then
 158try to speed things up, and measure again to confirm it actually _did_ speed
 159things up rather than made them worse.  (And understanding what's really going
 160on underneath is a big help to making it happen faster.)</p>
 161
 162<p>In general, being simple is better than being clever.  Optimization
 163strategies change with time.  For example, decades ago precalculating a table
 164of results (for things like isdigit() or cosine(int degrees)) was clearly
 165faster because processors were so slow.  Then processors got faster and grew
 166math coprocessors, and calculating the value each time became faster than
 167the table lookup (because the calculation fit in L1 cache but the lookup
 168had to go out to DRAM).  Then cache sizes got bigger (the Pentium M has
 1692 megabytes of L2 cache) and the table fit in cache, so the table became
 170fast again...  Predicting how changes in hardware will affect your algorithm
 171is difficult, and using ten year old optimization advice and produce
 172laughably bad results.  But being simple and efficient is always going to
 173give at least a reasonable result.</p>
 174
 175<p>The famous quote from Ken Thompson, "When in doubt, use brute force",
 176applies to toybox.  Do the simple thing first, do as little of it as possible,
 177and make sure it's right.  You can always speed it up later.</p>
 178
 179<b><h3>Size</h3></b>
 180<p>Again, being simple gives you most of this. An algorithm that does less work
 181is generally smaller.  Understand the problem, treat size as a cost, and
 182get a good bang for the byte.</p>
 183
 184<p>Understand the difference between binary size, heap size, and stack size.
 185Your binary is the executable file on disk, your heap is where malloc() memory
 186lives, and your stack is where local variables (and function call return
 187addresses) live.  Optimizing for binary size is generally good: executing
 188fewer instructions makes your program run faster (and fits more of it in
 189cache).  On embedded systems, binary size is especially precious because
 190flash is expensive (and its successor, MRAM, even more so).  Small stack size
 191is important for nommu systems because they have to preallocate their stack
 192and can't make it bigger via page fault.  And everybody likes a small heap.</p>
 193
 194<p>Measure the right things.  Especially with modern optimizers, expecting
 195something to be smaller is no guarantee it will be after the compiler's done
 196with it.  Binary size isn't the most accurate indicator of the impact of a
 197given change, because lots of things get combined and rounded during
 198compilation and linking.  Matt Mackall's bloat-o-meter is a python script
 199which compares two versions of a program, and shows size changes in each
 200symbol (using the "nm" command behind the scenes).  To use this, run
 201"make baseline" to build a baseline version to compare against, and
 202then "make bloatometer" to compare that baseline version against the current
 203code.</p>
 204
 205<p>Avoid special cases.  Whenever you see similar chunks of code in more than
 206one place, it might be possible to combine them and have the users call shared
 207code. (This is the most commonly cited trick, which doesn't make it easy. If
 208seeing two lines of code do the same thing makes you slightly uncomfortable,
 209you've got the right mindset.)</p>
 210
 211<p>Some specific advice: Using a char in place of an int when doing math
 212produces significantly larger code on some platforms (notably arm),
 213because each time the compiler has to emit code to convert it to int, do the
 214math, and convert it back.  Bitfields have this problem on most platforms.
 215Because of this, using char to index a for() loop is probably not a net win,
 216although using char (or a bitfield) to store a value in a structure that's
 217repeated hundreds of times can be a good tradeoff of binary size for heap
 218space.</p>
 219
 220<b><h3>Simplicity</h3></b>
 221
 222<p>Complexity is a cost, just like code size or runtime speed. Treat it as
 223a cost, and spend your complexity budget wisely. (Sometimes this means you
 224can't afford a feature because it complicates the code too much to be
 225worth it.)</p>
 226
 227<p>Simplicity has lots of benefits.  Simple code is easy to maintain, easy to
 228port to new processors, easy to audit for security holes, and easy to
 229understand.</p>
 230
 231<p>Simplicity itself can have subtle non-obvious aspects requiring a tradeoff
 232between one kind of simplicity and another: simple for the computer to
 233execute and simple for a human reader to understand aren't always the
 234same thing. A compact and clever algorithm that does very little work may
 235not be as easy to explain or understand as a larger more explicit version
 236requiring more code, memory, and CPU time. When balancing these, err on the
 237side of doing less work, but add comments describing how you
 238could be more explicit.</p>
 239
 240<p>In general, comments are not a substitute for good code (or well chosen
 241variable or function names). Commenting "x += y;" with "/* add y to x */"
 242can actually detract from the program's readability. If you need to describe
 243what the code is doing (rather than _why_ it's doing it), that means the
 244code itself isn't very clear.</p>
 245
 246<p>Environmental dependencies are another type of complexity, so needing other
 247packages to build or run is a big downside. For example, we don't use curses
 248when we can simply output ansi escape sequences and trust all terminal
 249programs written in the past 30 years to be able to support them. Regularly
 250testing that we work with C libraries which support static linking (musl does,
 251glibc doesn't) is another way to be self-contained with known boundaries:
 252it doesn't have to be the only way to build the project, but should be regularly
 253tested and supported.</p>
 254
 255<p>Prioritizing simplicity tends to serve our other goals: simplifying code
 256generally reduces its size (both in terms of binary size and runtime memory
 257usage), and avoiding unnecessary work makes code run faster. Smaller code
 258also tends to run faster on modern hardware due to CPU cacheing: fitting your
 259code into L1 cache is great, and staying in L2 cache is still pretty good.</p>
 260
 261<p>But a simple implementation is not always the smallest or fastest, and
 262balancing simplicity vs the other goals can be difficult. For example, the
 263atolx_range() function in lib/lib.c always uses the 64 bit "long long" type,
 264which produces larger and slower code on 32 bit platforms and
 265often assigned into smaller interger types. Although libc has parallel
 266implementations for different data sizes (atoi, atol, atoll) we chose a
 267common codepath which can cover all cases (every user goes through the
 268same codepath, with the maximum amount of testing and minimum and avoids
 269surprising variations in behavior).</p>
 270
 271<p>On the other hand, the "tail" command has two codepaths, one for seekable
 272files and one for nonseekable files. Although the nonseekable case can handle
 273all inputs (and is required when input comes from a pipe or similar, so cannot
 274be removed), reading through multiple gigabytes of data to reach the end of
 275seekable files was both a common case and hugely penalized by a nonseekable
 276approach (half-minute wait vs instant results). This is one example
 277where performance did outweigh simplicity of implementation.</p>
 278
 279<p><a href=http://www.joelonsoftware.com/articles/fog0000000069.html>Joel
 280Spolsky argues against throwing code out and starting over</a>, and he has
 281good points: an existing debugged codebase contains a huge amount of baked
 282in knowledge about strange real-world use cases that the designers didn't
 283know about until users hit the bugs, and most of this knowledge is never
 284explicitly stated anywhere except in the source code.</p>
 285
 286<p>That said, the Mythical Man-Month's "build one to throw away" advice points
 287out that until you've solved the problem you don't properly understand it, and
 288about the time you finish your first version is when you've finally figured
 289out what you _should_ have done.  (The corrolary is that if you build one
 290expecting to throw it away, you'll actually wind up throwing away two.  You
 291don't understand the problem until you _have_ solved it.)</p>
 292
 293<p>Joel is talking about what closed source software can afford to do: Code
 294that works and has been paid for is a corporate asset not lightly abandoned.
 295Open source software can afford to re-implement code that works, over and
 296over from scratch, for incremental gains.  Before toybox, the unix command line
 297has already been reimplemented from scratch several times (the
 298original AT&amp;T Unix command line in assembly and then in C, the BSD
 299versions, Coherent was the first full from-scratch Unix clone in 1980,
 300Minix was another clone which Linux was inspired by and developed under,
 301the GNU tools were yet another rewrite intended for use in the stillborn
 302"Hurd" project, BusyBox was still another rewrite, and more versions
 303were written in Plan 9, uclinux, klibc, sash, sbase, s6, and of course
 304android toolbox...). But maybe toybox can do a better job. :)</p>
 305
 306<p>As Antoine de St. Exupery (author of "The Little Prince" and an early
 307aircraft designer) said, "Perfection is achieved, not when there
 308is nothing left to add, but when there is nothing left to take away."
 309And Ken Thompson (creator of Unix) said "One of my most productive
 310days was throwing away 1000 lines of code." It's always possible to
 311come up with a better way to do it.</p>
 312
 313<p>P.S. How could I resist linking to an article about
 314<a href=http://blog.outer-court.com/archive/2005-08-24-n14.html>why
 315programmers should strive to be lazy and dumb</a>?</p>
 316
 317<a name="portability"><b><h2><a href="#portability">Portability issues</a></h2></b>
 318
 319<b><h3>Platforms</h3></b>
 320<p>Toybox should run on Android (all commands with musl-libc, as large a subset
 321as practical with bionic), and every other hardware platform Linux runs on.
 322Other posix/susv4 environments (perhaps MacOS X or newlib+libgloss) are vaguely
 323interesting but only if they're easy to support; I'm not going to spend much
 324effort on them.</p>
 325
 326<p>I don't do windows.</p>
 327
 328<p>We depend on C99 and posix-2008 libc features such as the openat() family of
 329functions. We also assume certain "modern" linux kernel behavior such
 330as large environment sizes (<a href=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b6a2fea39318>linux commit b6a2fea39318</a>, went into 2.6.22
 331released <a href=faq.html#support_horizon>July 2007</a>). In theory this shouldn't prevent us from working on
 332older kernels or other implementations (ala BSD), but we don't police their
 333corner cases.</p>
 334
 335<b><h3>32/64 bit</h3></b>
 336<p>Toybox should work on both 32 bit and 64 bit systems. 64 bit desktop
 337hardware went mainstream in 2005 and was essentially ubiquitous
 338by the end of the decade, but 32 bit hardware will continue to be important
 339in embedded devices for several more years.</p>
 340
 341<p>Toybox relies on the fact that on any Unix-like platform, pointer and long
 342are always the same size (on both 32 and 64 bit). Pointer and int are _not_
 343the same size on 64 bit systems, but pointer and long are.
 344This is guaranteed by the LP64 memory model, a Unix standard (which Linux
 345and MacOS X both implement, and which modern 64 bit processors such as
 346x86-64 were <a href=http://www.pagetable.com/?p=6>designed for</a>).  See
 347<a href=http://www.unix.org/whitepapers/64bit.html>the LP64 standard</a> and
 348<a href=http://www.unix.org/version2/whatsnew/lp64_wp.html>the LP64
 349rationale</a> for details.</p>
 350
 351<p>Note that Windows doesn't work like this, and I don't care.
 352<a href=http://blogs.msdn.com/oldnewthing/archive/2005/01/31/363790.aspx>The
 353insane legacy reasons why this is broken on Windows are explained here.</a></p>
 354
 355<b><h3>Signedness of char</h3></b>
 356<p>On platforms like x86, variables of type char default to unsigned.  On
 357platforms like arm, char defaults to signed.  This difference can lead to
 358subtle portability bugs, and to avoid them we specify which one we want by
 359feeding the compiler -funsigned-char.</p>
 360
 361<p>The reason to pick "unsigned" is that way char strings are 8-bit clean by
 362default, which makes UTF-8 support easier.</p>
 363
 364<p><h3>Error messages and internationalization:</h3></p>
 365
 366<p>Error messages are extremely terse not just to save bytes, but because we
 367don't use any sort of _("string") translation infrastructure. (We're not
 368translating the command names themselves, so we must expect a minimum amount of
 369english knowledge from our users, but let's keep it to a minimum.)</p>
 370
 371<p>Thus "bad -A '%c'" is
 372preferable to "Unrecognized address base '%c'", because a non-english speaker
 373can see that -A was the problem (giving back the command line argument they
 374supplied). A user with a ~20 word english vocabulary is
 375more likely to know (or guess) "bad" than the longer message, and you can
 376use "bad" in place of "invalid", "inappropriate", "unrecognized"...
 377Similarly when atolx_range() complains about range constraints with
 378"4 < 17" or "12 > 5", it's intentional: those don't need to be translated.</p>
 379
 380<p>The strerror() messages produced by perror_exit() and friends should be
 381localized by libc, and our error functions also prepend the command name
 382(which non-english speakers can presumably recognize already). Keep the
 383explanation in between to a minimum, and where possible feed back the values
 384they passed in to identify _what_ we couldn't process.
 385If you say perror_exit("setsockopt"), you've identified the action you
 386were trying to take, and the perror gives a translated error message (from libc)
 387explaining _why_ it couldn't do it, so you probably don't need to add english
 388words like "failed" or "couldn't assign".</p>
 389
 390<p>All commands should be 8-bit clean, with explicit
 391<a href=http://yarchive.net/comp/linux/utf8.html>UTF-8</a> support where
 392necessary. Assume all input data might be utf8, and at least preserve
 393it and pass it through. (For this reason, our build is -funsigned-char on
 394all architectures; "char" is unsigned unless you stick "signed" in front
 395of it.)</p>
 396
 397<p>Locale support isn't currently a goal; that's a presentation layer issue
 398(I.E. a GUI problem).</p>
 399
 400<p>Someday we should probably have translated --help text, but that's a
 401post-1.0 issue.</p>
 402
 403<p><h3>Shared Libraries</h3></p>
 404
 405<p>Toybox's policy on shared libraries is that they should never be
 406required, but can optionally be used to improve performance.</p>
 407
 408<p>Toybox should provide the command line utilities for
 409<a href=roadmap.html#dev_env>self-hosting development envirionments</a>,
 410and an easy way to set up "hermetic builds" (I.E. builds which provide
 411their own dependencies, isolating the build logic from host command version
 412skew with a simple known build environment). In both cases, external
 413dependencies defeat the purpose.</p>
 414
 415<p>This means toybox should provide full functionality without relying
 416on any external dependencies (other than libc). But toybox may optionally use
 417libraries such as zlib and openssl to improve performance for things like
 418deflate and sha1sum, which lets the corresponding built-in implementations
 419be simple (and thus slow). But the built-in implementations need to exist and
 420work.</p>
 421
 422<p>(This is why we use an external https wrapper program, because depending on
 423openssl or similar to be linked in would change the behavior of toybox.)</p>
 424
 425<a name="license" />
 426<h2>License</h2>
 427
 428<p>Toybox is licensed <a href=license.html>0BSD</a>, which is a public domain
 429equivalent license approved by <a href=https://spdx.org/licenses/0BSD.html>SPDX</a>. This works like other BSD licenses except that it doesn't
 430require copying specific license text into the resulting project when
 431you copy code. (We care about attribution, not ownership, and the internet's
 432really good at pointing out plagiarism.)</p>
 433
 434<p>This means toybox usually can't use external code contributions, and must
 435implement new versions of everything unless the external code's original
 436author (and any additional contributors) grants permission to relicense.
 437Just as a GPLv2 project can't incorporate GPLv3 code and a BSD-licensed
 438project can't incorporate either kind of GPL code, we can't incorporate
 439most BSD or Apache licensed code without changing our license terms.</p>
 440
 441<p>The exception to this is code under an existing public domain equivalent
 442license, such as the xz decompressor or
 443<a href=https://github.com/mkj/dropbear/blob/master/libtommath/LICENSE>libtommath</a> and <a href=https://github.com/mkj/dropbear/blob/master/libtomcrypt/LICENSE>libtomcrypt</a>.</p>
 444
 445<a name="codestyle" />
 446<h2>Coding style</h2>
 447
 448<p>The real coding style holy wars are over things that don't matter
 449(whitespace, indentation, curly bracket placement...) and thus have no
 450obviously correct answer. As in academia, "the fighting is so vicious because
 451the stakes are so small". That said, being consistent makes the code readable,
 452so here's how to make toybox code look like other toybox code.</p>
 453
 454<p>Toybox source uses two spaces per indentation level, and wraps at 80
 455columns. (Indentation of continuation lines is awkward no matter what
 456you do, sometimes two spaces looks better, sometimes indenting to the
 457contents of a parentheses looks better.)</p>
 458
 459<p>I'm aware this indentation style creeps some people out, so here's
 460the sed invocation to convert groups of two leading spaces to tabs:</p>
 461<blockquote><pre>
 462sed -i ':loop;s/^\( *\)  /\1\t/;t loop' filename
 463</pre></blockquote>
 464
 465<p>And here's the sed invocation to convert leading tabs to two spaces each:</p>
 466<blockquote><pre>
 467sed -i ':loop;s/^\( *\)\t/\1  /;t loop' filename
 468</pre></blockquote>
 469
 470<p>There's a space after C flow control statements that look like functions, so
 471"if (blah)" instead of "if(blah)". (Note that sizeof is actually an
 472operator, so we don't give it a space for the same reason ++ doesn't get
 473one. Yeah, it doesn't need the parentheses either, but it gets them.
 474These rules are mostly to make the code look consistent, and thus easier
 475to read.) We also put a space around assignment operators (on both sides),
 476so "int x = 0;".</p>
 477
 478<p>Blank lines (vertical whitespace) go between thoughts. "We were doing that,
 479now we're doing this." (Not a hard and fast rule about _where_ it goes,
 480but there should be some for the same reason writing has paragraph breaks.)</p>
 481
 482<p>Variable declarations go at the start of blocks, with a blank line between
 483them and other code. Yes, c99 allows you to put them anywhere, but they're
 484harder to find if you do that. If there's a large enough distance between
 485the declaration and the code using it to make you uncomfortable, maybe the
 486function's too big, or is there an if statement or something you can
 487use as an excuse to start a new closer block? Use a longer variable name
 488that's easier to search for perhaps?</p>
 489
 490<p>An * binds to a variable name not a type name, so space it that way.
 491(In C "char *a, b;" and "char* a, b;" mean the same thing: "a" is a pointer
 492but "b" is not. Spacing it the second way is not how C works.)</p>
 493
 494<p>If statements with a single line body go on the same line if the result
 495fits in 80 columns, on a second line if it doesn't. We usually only use
 496curly brackets if we need to, either because the body is multiple lines or
 497because we need to distinguish which if an else binds to. Curly brackets go
 498on the same line as the test/loop statement. The exception to both cases is
 499if the test part of an if statement is long enough to split into multiple
 500lines, then we put the curly bracket on its own line afterwards (so it doesn't
 501get lost in the multple line variably indented mess), and we put it there
 502even if it's only grouping one line (because the indentation level is not
 503providing clear information in that case).</p>
 504
 505<p>I.E.</p>
 506
 507<blockquote>
 508<pre>
 509if (thingy) thingy;
 510else thingy;
 511
 512if (thingy) {
 513  thingy;
 514  thingy;
 515} else thingy;
 516
 517if (blah blah blah...
 518    && blah blah blah)
 519{
 520  thingy;
 521}
 522</pre></blockquote>
 523
 524<p>Gotos are allowed for error handling, and for breaking out of
 525nested loops. In general, a goto should only jump forward (not back), and
 526should either jump to the end of an outer loop, or to error handling code
 527at the end of the function. Goto labels are never indented: they override the
 528block structure of the file. Putting them at the left edge makes them easy
 529to spot as overrides to the normal flow of control, which they are.</p>
 530
 531<p>When there's a shorter way to say something, we tend to do that for
 532consistency. For example, we tend to say "*blah" instead of "blah[0]" unless
 533we're referring to more than one element of blah. Similarly, NULL is
 534really just 0 (and C will automatically typecast 0 to anything, except in
 535varargs), "if (function() != NULL)" is the same as "if (function())",
 536"x = (blah == NULL);" is "x = !blah;", and so on.</p>
 537
 538<p>The goal is to be
 539concise, not cryptic: if you're worried about the code being hard to
 540understand, splitting it to multiple steps on multiple lines is
 541better than a NOP operation like "!= NULL". A common sign of trying too
 542hard is nesting ? : three levels deep, sometimes if/else and a temporary
 543variable is just plain easier to read. If you think you need a comment,
 544you may be right.</p>
 545
 546<p>Comments are nice, but don't overdo it. Comments should explain _why_,
 547not how. If the code doesn't make the how part obvious, that's a problem with
 548the code. Sometimes choosing a better variable name is more revealing than a
 549comment. Comments on their own line are better than comments on the end of
 550lines, and they usually have a blank line before them. Most of toybox's
 551comments are c99 style // single line comments, even when there's more than
 552one of them. The /* multiline */ style is used at the start for the metadata,
 553but not so much in the code itself. They don't nest cleanly, are easy to leave
 554accidentally unterminated, need extra nonfunctional * to look right, and if
 555you need _that_ much explanation maybe what you really need is a URL citation
 556linking to a standards document? Long comments can fall out of sync with what
 557the code is doing. Comments do not get regression tested. There's no such
 558thing as self-documenting code (if nothing else, code with _no_ comments
 559is a bit unfriendly to new readers), but "chocolate sauce isn't the answer
 560to bad cooking" either. Don't use comments as a crutch to explain unclear
 561code if the code can be fixed.</p>
 562
 563<!--#include file="footer.html" -->
 564