1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Mu - linux/bootstrap/000organization.cc</title>
<meta name="Generator" content="Vim/8.2">
<meta name="plugin-version" content="vim8.1_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=,use_input_for_pc=fallback">
<meta name="colorscheme" content="minimal-light">
<style>
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffd7; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #ffffd7; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.PreProc { color: #c000c0; }
.LineNr { }
.Delimiter { color: #c000c0; }
.cSpecial { color: #008000; }
.Normal { color: #000000; background-color: #ffffd7; padding-bottom: 1px; }
.Comment { color: #005faf; }
.Constant { color: #008787; }
.Identifier { color: #af5f00; }
-->
</style>
<script>
<!--
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
var lineNum;
lineNum = window.location.hash;
lineNum = lineNum.substr(1); /* strip off '#' */
if (lineNum.indexOf('L') == -1) {
lineNum = 'L'+lineNum;
}
var lineElem = document.getElementById(lineNum);
/* Always jump to new location even if the line was hidden inside a fold, or
* we corrected the raw number to a line ID.
*/
if (lineElem) {
lineElem.scrollIntoView(true);
}
return true;
}
if ('onhashchange' in window) {
window.onhashchange = JumpToLine;
}
-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/main/linux/bootstrap/000organization.cc'>https://github.com/akkartik/mu/blob/main/linux/bootstrap/000organization.cc</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Comment">//: You guessed right: the '000' prefix means you should start reading here.</span>
<span id="L2" class="LineNr"> 2 </span><span class="Comment">//:</span>
<span id="L3" class="LineNr"> 3 </span><span class="Comment">//: This project is set up to load all files with a numeric prefix. Just</span>
<span id="L4" class="LineNr"> 4 </span><span class="Comment">//: create a new file and start hacking.</span>
<span id="L5" class="LineNr"> 5 </span><span class="Comment">//:</span>
<span id="L6" class="LineNr"> 6 </span><span class="Comment">//: The first few files (00*) are independent of what this program does, an</span>
<span id="L7" class="LineNr"> 7 </span><span class="Comment">//: experimental skeleton that will hopefully make it both easier for others to</span>
<span id="L8" class="LineNr"> 8 </span><span class="Comment">//: understand and more malleable, easier to rewrite and remould into radically</span>
<span id="L9" class="LineNr"> 9 </span><span class="Comment">//: different shapes without breaking in subtle corner cases. The premise is</span>
<span id="L10" class="LineNr"> 10 </span><span class="Comment">//: that understandability and rewrite-friendliness are related in a virtuous</span>
<span id="L11" class="LineNr"> 11 </span><span class="Comment">//: cycle. Doing one well makes it easier to do the other.</span>
<span id="L12" class="LineNr"> 12 </span><span class="Comment">//:</span>
<span id="L13" class="LineNr"> 13 </span><span class="Comment">//: Lower down, this file contains a legal, bare-bones C++ program. It doesn't</span>
<span id="L14" class="LineNr"> 14 </span><span class="Comment">//: do anything yet; subsequent files will contain :(...) directives to insert</span>
<span id="L15" class="LineNr"> 15 </span><span class="Comment">//: lines into it. For example:</span>
<span id="L16" class="LineNr"> 16 </span><span class="Comment">//: :(after "more events")</span>
<span id="L17" class="LineNr"> 17 </span><span class="Comment">//: This directive means: insert the following lines after a line in the</span>
<span id="L18" class="LineNr"> 18 </span><span class="Comment">//: program containing the words "more events".</span>
<span id="L19" class="LineNr"> 19 </span><span class="Comment">//:</span>
<span id="L20" class="LineNr"> 20 </span><span class="Comment">//: A simple tool is included to 'tangle' all the files together in sequence</span>
<span id="L21" class="LineNr"> 21 </span><span class="Comment">//: according to their directives into a single source file containing all the</span>
<span id="L22" class="LineNr"> 22 </span><span class="Comment">//: code for the project, and then feed the source file to the compiler.</span>
<span id="L23" class="LineNr"> 23 </span><span class="Comment">//: (It'll drop these comments starting with a '//:' prefix that only make</span>
<span id="L24" class="LineNr"> 24 </span><span class="Comment">//: sense before tangling.)</span>
<span id="L25" class="LineNr"> 25 </span><span class="Comment">//:</span>
<span id="L26" class="LineNr"> 26 </span><span class="Comment">//: Directives free up the programmer to order code for others to read rather</span>
<span id="L27" class="LineNr"> 27 </span><span class="Comment">//: than as forced by the computer or compiler. Each individual feature can be</span>
<span id="L28" class="LineNr"> 28 </span><span class="Comment">//: organized in a self-contained 'layer' that adds code to many different data</span>
<span id="L29" class="LineNr"> 29 </span><span class="Comment">//: structures and functions all over the program. The right decomposition into</span>
<span id="L30" class="LineNr"> 30 </span><span class="Comment">//: layers will let each layer make sense in isolation.</span>
<span id="L31" class="LineNr"> 31 </span><span class="Comment">//:</span>
<span id="L32" class="LineNr"> 32 </span><span class="Comment">//: "If I look at any small part of it, I can see what is going on -- I don't</span>
<span id="L33" class="LineNr"> 33 </span><span class="Comment">//: need to refer to other parts to understand what something is doing.</span>
<span id="L34" class="LineNr"> 34 </span><span class="Comment">//:</span>
<span id="L35" class="LineNr"> 35 </span><span class="Comment">//: If I look at any large part in overview, I can see what is going on -- I</span>
<span id="L36" class="LineNr"> 36 </span><span class="Comment">//: don't need to know all the details to get it.</span>
<span id="L37" class="LineNr"> 37 </span><span class="Comment">//:</span>
<span id="L38" class="LineNr"> 38 </span><span class="Comment">//: Every level of detail is as locally coherent and as well thought-out as</span>
<span id="L39" class="LineNr"> 39 </span><span class="Comment">//: any other level."</span>
<span id="L40" class="LineNr"> 40 </span><span class="Comment">//:</span>
<span id="L41" class="LineNr"> 41 </span><span class="Comment">//: -- Richard Gabriel, "The Quality Without A Name"</span>
<span id="L42" class="LineNr"> 42 </span><span class="Comment">//: (<a href="http://dreamsongs.com/Files/PatternsOfSoftware.pdf">http://dreamsongs.com/Files/PatternsOfSoftware.pdf</a>, page 42)</span>
<span id="L43" class="LineNr"> 43 </span><span class="Comment">//:</span>
<span id="L44" class="LineNr"> 44 </span><span class="Comment">//: Directives are powerful; they permit inserting or modifying any point in</span>
<span id="L45" class="LineNr"> 45 </span><span class="Comment">//: the program. Using them tastefully requires mapping out specific lines as</span>
<span id="L46" class="LineNr"> 46 </span><span class="Comment">//: waypoints for future layers to hook into. Often such waypoints will be in</span>
<span id="L47" class="LineNr"> 47 </span><span class="Comment">//: comments, capitalized to hint that other layers rely on their presence.</span>
<span id="L48" class="LineNr"> 48 </span><span class="Comment">//:</span>
<span id="L49" class="LineNr"> 49 </span><span class="Comment">//: A single waypoint might have many different code fragments hooking into</span>
<span id="L50" class="LineNr"> 50 </span><span class="Comment">//: it from all over the codebase. Use 'before' directives to insert</span>
<span id="L51" class="LineNr"> 51 </span><span class="Comment">//: code at a location in order, top to bottom, and 'after' directives to</span>
<span id="L52" class="LineNr"> 52 </span><span class="Comment">//: insert code in reverse order. By convention waypoints intended for insertion</span>
<span id="L53" class="LineNr"> 53 </span><span class="Comment">//: before begin with 'End'. Notice below how the layers line up above the "End</span>
<span id="L54" class="LineNr"> 54 </span><span class="Comment">//: Foo" waypoint.</span>
<span id="L55" class="LineNr"> 55 </span><span class="Comment">//:</span>
<span id="L56" class="LineNr"> 56 </span><span class="Comment">//: File 001 File 002 File 003</span>
<span id="L57" class="LineNr"> 57 </span><span class="Comment">//: ============ =================== ===================</span>
<span id="L58" class="LineNr"> 58 </span><span class="Comment">//: // Foo</span>
<span id="L59" class="LineNr"> 59 </span><span class="Comment">//: ------------</span>
<span id="L60" class="LineNr"> 60 </span><span class="Comment">//: <---- :(before "End Foo")</span>
<span id="L61" class="LineNr"> 61 </span><span class="Comment">//: ....</span>
<span id="L62" class="LineNr"> 62 </span><span class="Comment">//: ...</span>
<span id="L63" class="LineNr"> 63 </span><span class="Comment">//: ------------</span>
<span id="L64" class="LineNr"> 64 </span><span class="Comment">//: <---------------------------- :(before "End Foo")</span>
<span id="L65" class="LineNr"> 65 </span><span class="Comment">//: ....</span>
<span id="L66" class="LineNr"> 66 </span><span class="Comment">//: ...</span>
<span id="L67" class="LineNr"> 67 </span><span class="Comment">//: // End Foo</span>
<span id="L68" class="LineNr"> 68 </span><span class="Comment">//: ============</span>
<span id="L69" class="LineNr"> 69 </span><span class="Comment">//:</span>
<span id="L70" class="LineNr"> 70 </span><span class="Comment">//: Here's part of a layer in color: <a href="http://i.imgur.com/0eONnyX.png">http://i.imgur.com/0eONnyX.png</a>. Directives</span>
<span id="L71" class="LineNr"> 71 </span><span class="Comment">//: are shaded dark.</span>
<span id="L72" class="LineNr"> 72 </span><span class="Comment">//:</span>
<span id="L73" class="LineNr"> 73 </span><span class="Comment">//: Layers do more than just shuffle code around. In a well-organized codebase</span>
<span id="L74" class="LineNr"> 74 </span><span class="Comment">//: it should be possible to stop loading after any file/layer, build and run</span>
<span id="L75" class="LineNr"> 75 </span><span class="Comment">//: the program, and pass all tests for loaded features. (Relevant is</span>
<span id="L76" class="LineNr"> 76 </span><span class="Comment">//: <a href="http://youtube.com/watch?v=c8N72t7aScY">http://youtube.com/watch?v=c8N72t7aScY</a>, a scene from "2001: A Space</span>
<span id="L77" class="LineNr"> 77 </span><span class="Comment">//: Odyssey".) Get into the habit of running the included script called</span>
<span id="L78" class="LineNr"> 78 </span><span class="Comment">//: 'test_layers' before you commit any changes.</span>
<span id="L79" class="LineNr"> 79 </span><span class="Comment">//:</span>
<span id="L80" class="LineNr"> 80 </span><span class="Comment">//: This 'subsetting guarantee' ensures that this directory contains a</span>
<span id="L81" class="LineNr"> 81 </span><span class="Comment">//: cleaned-up narrative of the evolution of this codebase. Organizing</span>
<span id="L82" class="LineNr"> 82 </span><span class="Comment">//: autobiographically allows newcomers to rapidly orient themselves, reading</span>
<span id="L83" class="LineNr"> 83 </span><span class="Comment">//: the first few files to understand a simple gestalt of a program's core</span>
<span id="L84" class="LineNr"> 84 </span><span class="Comment">//: purpose and features, and later gradually working their way through other</span>
<span id="L85" class="LineNr"> 85 </span><span class="Comment">//: features as the need arises.</span>
<span id="L86" class="LineNr"> 86 </span><span class="Comment">//:</span>
<span id="L87" class="LineNr"> 87 </span><span class="Comment">//: Programmers shouldn't need to understand everything about a program to</span>
<span id="L88" class="LineNr"> 88 </span><span class="Comment">//: hack on it. But they shouldn't be prevented from a thorough understanding</span>
<span id="L89" class="LineNr"> 89 </span><span class="Comment">//: of each aspect either. The goal of layers is to reward curiosity.</span>
<span id="L90" class="LineNr"> 90 </span><span class="Comment">//:</span>
<span id="L91" class="LineNr"> 91 </span><span class="Comment">//: More information: <a href="http://akkartik.name/post/wart-layers">http://akkartik.name/post/wart-layers</a></span>
<span id="L92" class="LineNr"> 92 </span>
<span id="L93" class="LineNr"> 93 </span><span class="Comment">// Includes</span>
<span id="L94" class="LineNr"> 94 </span><span class="Comment">// End Includes</span>
<span id="L95" class="LineNr"> 95 </span>
<span id="L96" class="LineNr"> 96 </span><span class="Comment">// Types</span>
<span id="L97" class="LineNr"> 97 </span><span class="Comment">// End Types</span>
<span id="L98" class="LineNr"> 98 </span>
<span id="L99" class="LineNr"> 99 </span><span class="Comment">// Function prototypes are auto-generated in the 'build' script; define your</span>
<span id="L100" class="LineNr">100 </span><span class="Comment">// functions in any order. Just be sure to declare each function header all on</span>
<span id="L101" class="LineNr">101 </span><span class="Comment">// one line, ending with the '{'. Our auto-generation scripts are too minimal</span>
<span id="L102" class="LineNr">102 </span><span class="Comment">// and simple-minded to handle anything else.</span>
<span id="L103" class="LineNr">103 </span><span class="PreProc">#include </span><span class="Constant">"function_list"</span> <span class="Comment">// by convention, files ending with '_list' are auto-generated</span>
<span id="L104" class="LineNr">104 </span>
<span id="L105" class="LineNr">105 </span><span class="Comment">// Globals</span>
<span id="L106" class="LineNr">106 </span><span class="Comment">//</span>
<span id="L107" class="LineNr">107 </span><span class="Comment">// All statements in this section should always define a single variable on a</span>
<span id="L108" class="LineNr">108 </span><span class="Comment">// single line. The 'build' script will simple-mindedly auto-generate extern</span>
<span id="L109" class="LineNr">109 </span><span class="Comment">// declarations for them. Remember to define (not just declare) constants with</span>
<span id="L110" class="LineNr">110 </span><span class="Comment">// extern linkage in this section, since C++ global constants have internal</span>
<span id="L111" class="LineNr">111 </span><span class="Comment">// linkage by default.</span>
<span id="L112" class="LineNr">112 </span><span class="Comment">//</span>
<span id="L113" class="LineNr">113 </span><span class="Comment">// End Globals</span>
<span id="L114" class="LineNr">114 </span>
<span id="L115" class="LineNr">115 </span><span class="Normal">int</span> <a href='000organization.cc.html#L115'>main</a><span class="Delimiter">(</span><span class="Normal">int</span> argc<span class="Delimiter">,</span> <span class="Normal">char</span>* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L116" class="LineNr">116 </span> atexit<span class="Delimiter">(</span><a href='000organization.cc.html#L150'>reset</a><span class="Delimiter">);</span>
<span id="L117" class="LineNr">117 </span> <span class="Comment">// we require a 32-bit little-endian system</span>
<span id="L118" class="LineNr">118 </span> assert<span class="Delimiter">(</span><span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">int</span><span class="Delimiter">)</span> == <span class="Constant">4</span><span class="Delimiter">);</span>
<span id="L119" class="LineNr">119 </span> assert<span class="Delimiter">(</span><span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">float</span><span class="Delimiter">)</span> == <span class="Constant">4</span><span class="Delimiter">);</span>
<span id="L120" class="LineNr">120 </span> <a href='000organization.cc.html#L154'>assert_little_endian</a><span class="Delimiter">();</span>
<span id="L121" class="LineNr">121 </span>
<span id="L122" class="LineNr">122 </span> <span class="Comment">// End One-time Setup</span>
<span id="L123" class="LineNr">123 </span>
<span id="L124" class="LineNr">124 </span> <span class="Comment">// Commandline Parsing</span>
<span id="L125" class="LineNr">125 </span> <span class="Comment">// End Commandline Parsing</span>
<span id="L126" class="LineNr">126 </span>
<span id="L127" class="LineNr">127 </span> <span class="Comment">// End Main</span>
<span id="L128" class="LineNr">128 </span>
<span id="L129" class="LineNr">129 </span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
<span id="L130" class="LineNr">130 </span><span class="Delimiter">}</span>
<span id="L131" class="LineNr">131 </span>
<span id="L132" class="LineNr">132 </span><span class="Comment">// Unit Tests</span>
<span id="L133" class="LineNr">133 </span><span class="Comment">// End Unit Tests</span>
<span id="L134" class="LineNr">134 </span>
<span id="L135" class="LineNr">135 </span><span class="Comment">//: our first directive; insert the following headers at the start of the program</span>
<span id="L136" class="LineNr">136 </span><span class="Delimiter">:(before "End Includes")</span>
<span id="L137" class="LineNr">137 </span><span class="PreProc">#include </span><span class="Constant"><assert.h></span>
<span id="L138" class="LineNr">138 </span><span class="PreProc">#include </span><span class="Constant"><stdlib.h></span>
<span id="L139" class="LineNr">139 </span>
<span id="L140" class="LineNr">140 </span><span class="Comment">//: Without directives or with the :(code) directive, lines get added at the</span>
<span id="L141" class="LineNr">141 </span><span class="Comment">//: end.</span>
<span id="L142" class="LineNr">142 </span><span class="Comment">//:</span>
<span id="L143" class="LineNr">143 </span><span class="Comment">//: Regardless of where functions are defined, we can call them anywhere we</span>
<span id="L144" class="LineNr">144 </span><span class="Comment">//: like as long as we format the function header in a specific way: put it</span>
<span id="L145" class="LineNr">145 </span><span class="Comment">//: all on a single line without indent, end the line with ') {' and no</span>
<span id="L146" class="LineNr">146 </span><span class="Comment">//: trailing whitespace. As long as functions uniformly start this way, our</span>
<span id="L147" class="LineNr">147 </span><span class="Comment">//: 'build' script contains a little command to automatically generate</span>
<span id="L148" class="LineNr">148 </span><span class="Comment">//: declarations for them.</span>
<span id="L149" class="LineNr">149 </span><span class="Delimiter">:(code)</span>
<span id="L150" class="LineNr">150 </span><span class="Normal">void</span> <a href='000organization.cc.html#L150'>reset</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L151" class="LineNr">151 </span> <span class="Comment">// End Reset</span>
<span id="L152" class="LineNr">152 </span><span class="Delimiter">}</span>
<span id="L153" class="LineNr">153 </span>
<span id="L154" class="LineNr">154 </span><span class="Normal">void</span> <a href='000organization.cc.html#L154'>assert_little_endian</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L155" class="LineNr">155 </span> <span class="Normal">const</span> <span class="Normal">int</span> x = <span class="Constant">1</span><span class="Delimiter">;</span>
<span id="L156" class="LineNr">156 </span> <span class="Normal">const</span> <span class="Normal">char</span>* y = <span class="Normal">reinterpret_cast</span><<span class="Normal">const</span> <span class="Normal">char</span>*><span class="Delimiter">(</span>&x<span class="Delimiter">);</span>
<span id="L157" class="LineNr">157 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>*y != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span id="L158" class="LineNr">158 </span> cerr << <span class="Constant">"SubX requires a little-endian processor. Do you have Intel (or AMD or Atom) inside?</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span>
<span id="L159" class="LineNr">159 </span> exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
<span id="L160" class="LineNr">160 </span> <span class="Delimiter">}</span>
<span id="L161" class="LineNr">161 </span><span class="Delimiter">}</span>
<span id="L162" class="LineNr">162 </span><span class="Delimiter">:(before "End Includes")</span>
<span id="L163" class="LineNr">163 </span><span class="PreProc">#include</span><span class="Constant"><iostream></span>
<span id="L164" class="LineNr">164 </span><span class="Normal">using</span> std::cerr<span class="Delimiter">;</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|