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&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