SaltyCrane: c_cplusplushttps://www.saltycrane.com/blog/2009-07-08T17:28:02-07:00Notes on C++ development with Emacs on Ubuntu Linux
2009-07-08T17:28:02-07:00https://www.saltycrane.com/blog/2009/07/notes-c-development-emacs-ubuntu-linux/<p>
Here are my notes on setting up an Emacs C++ development environment.
I'm using <a href="http://gcc.gnu.org/">GNU g++</a> (4.3.3),
<a href="http://www.gnu.org/software/make/">GNU make</a> (3.81),
<a href="http://www.gnu.org/software/gdb/">GNU gdb</a> (3.8-debian),
and <a href="http://www.gnu.org/software/emacs/">GNU emacs</a> (23.0.92.1 built from CVS 2009-04-22)
on <a href="http://www.ubuntu.com/">Ubuntu Linux</a> (9.04 Jaunty Jackalope).
</p>
<h4>Install tools</h4>
<p>If you don't already have <code>g++</code>, <code>make</code>, and <code>gdb</code>, install them:</p>
<pre>sudo apt-get install g++ make gdb</pre>
<h4>Create files</h4>
<ul>
<li>Create a project directory:
<pre>mkdir helloworld</pre>
</li>
<li>Create a source file <code>helloworld/hello.cpp</code>:
<pre>#include <iostream>
int main(void)
{
char greeting[] = "Hello World!";
std::cout << greeting << std::endl;
return 0;
}</pre>
</li>
<li>Create a makefile <code>helloworld/Makefile</code>:
<pre class="Makefile"># Makefile for GNU g++
CC=g++
CFLAGS=-g -Wall
all: hello
hello: hello.cpp
$(CC) $(CFLAGS) -o hello hello.cpp
clean:
rm hello
</pre>
</li>
</ul>
<h4>Compile within Emacs</h4>
<p>See also: <a href="http://www.gnu.org/software/emacs/manual/html_mono/emacs.html.gz#Building">
32 Compiling and Testing Programs</a> in the GNU Emacs manual.</p>
<ul>
<li>Open <code>hello.cpp</code> in Emacs</li>
<li>
<pre>M-x compile RET</pre>
<pre>make -k RET</pre>
<p><em>Note:</em> The default compile command is <code>make -k</code>.
You can change the default command by setting the <code>compile-command</code>
variable in your <code>.emacs</code> file.</p>
</li>
<li>Useful commands in the compilation window:
<ul>
<li><code>C-x `</code>: Go to next error in the code</li>
<li><code>M-n</code>: Go to next error message</li>
<li><code>M-p</code>: Go to previous error message</li>
<li><code>RET</code>: Go to the source code for the current error message</li>
</ul>
</li>
</ul>
<h4>Run using Emacs shell</h4>
<ul>
<li>
<pre>M-! ./hello RET</pre>
<p>You should see the output in the minibuffer.</p>
</li>
</ul>
<h4>Debug with gdb in Emacs</h4>
<p>For more information see:
<a href="http://www.gnu.org/software/emacs/manual/html_mono/emacs.html.gz#Debuggers">
32.6 Running Debuggers Under Emacs</a> in the GNU Emacs manual.</p>
<ul>
<li>To show multiple debugging windows such as breakpoints, locals, etc.,
set the <code>gdb-many-windows</code> variable in <code>~/.emacs</code>:
<pre>(setq gdb-many-windows t)</pre>
Restart Emacs.<br><br>
</li>
<li>Start the debugger. While visiting <code>helloworld/hello.cpp</code>:
<pre>M-x gdb RET --annotate=3 hello RET</pre>
</li>
<li>Set a breakpoint by clicking in the left margin at the desired location.</li>
<li>Run the debugger by typing <code>run</code> at the <code>(gdb)</code> prompt
in the <code>*gud-hello*</code> buffer.
</li>
<li>In the GUD buffer, use the following commands:
<ul>
<li><code>C-c C-s</code> Step into</li>
<li><code>C-c C-n</code> Stev over</li>
<li><code>C-c C-p</code> Evaluate the expression at point.</li>
<li><code>C-c C-r</code> Continue</li>
<li><code>C-c C-u</code> Continue until current line</li>
</ul>
<br>
</li>
<li>When finished, type <code>quit</code> at the <code>(gdb)</code> prompt.</li>
</ul>
<h4>Documentation:</h4>
<ul>
<li><a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/">GNU gcc 4.4</a></li>
<li><a href="http://www.gnu.org/software/make/manual/make.html">GNU make</a></li>
<li><a href="http://www.gnu.org/software/emacs/manual/">GNU Emacs manuals</a></li>
<li><a href="http://sourceware.org/gdb/current/onlinedocs/gdb_toc.html">GNU gdb</a></li>
</ul>
<h4>References</h4>
<ul>
<li><em>Practical C++ Programming, 2nd Edition</em> by Steve Oualine (2004)</li>
<li><em>Learning GNU Emacs, 3rd Edition</em> by Debra Cameron et al. (2004)</li>
<li><a href="http://www.linuxjournal.com/article/5765">Emacs: the Free Software IDE</a>
at the Linux Journal (2002)</li>
</ul>
How to reverse words in a sentence using Python and C
2009-04-22T09:56:32-07:00https://www.saltycrane.com/blog/2009/04/how-reverse-words-sentence-using-python-and-c/<p>This is a technical problem I attempted recently.
The problem was to reverse the words in a sentence.
For example, <em>The quick brown fox
jumped over the lazy dog.</em> becomes <em>dog. lazy the
over jumped fox brown quick The</em>.
I had to solve the problem first using Python, and then using C.
In addition, the C
version could only use 1 extra character of memory. I solved
the Python version easily, but the C version was too difficult
for me. Here are possible solutions.
</p>
<h4>Python version</h4>
<pre class="python">sentence = "The quick brown fox jumped over the lazy dog."
words = sentence.split()
sentence_rev = " ".join(reversed(words))
print sentence_rev</pre>
<br>
<h4>C version</h4>
<p>Credit for this solution goes to
<a href="http://wuhrr.wordpress.com/2007/11/09/how-to-reverse-words-within-a-sentence-in-c/">
Hai Vu</a></p>
<pre class="c">#include <stdio.h>
/* function declarations */
void reverse_words(char *sentence);
void reverse_chars(char *left, char *right);
/* main program */
int main()
{
char mysentence[] = "The quick brown fox jumped over the lazy dog.";
reverse_words(mysentence);
printf("%s\n", mysentence);
return 0;
}
/* reverse the words in a sentence */
void reverse_words(char *sentence)
{
char *start = sentence;
char *end = sentence;
/* find the end of the sentence */
while (*end != '\0') {
++end;
}
--end;
/* reverse the characters in the sentence */
reverse_chars(start, end);
/* reverse the characters in each word */
while (*start != '\0') {
/* move start pointer to the beginning of the next word */
for (; *start != '\0' && *start == ' '; start++) ;
/* move end pointer to the end of the next word */
for (end=start; *end != '\0' && *end != ' '; end++) ;
--end;
/* reverse the characters in the word */
reverse_chars(start, end);
/* move to next word */
start = ++end;
}
}
/* reverse the characters in a string */
void reverse_chars(char *left, char *right)
{
char temp;
while( left < right) {
temp = *left;
*left = *right;
*right = temp;
++left;
--right;
}
}</pre>
How to search C code for division or sqrt
2008-07-24T15:12:20-07:00https://www.saltycrane.com/blog/2008/07/how-search-c-code-division-or-sqrt/<p>The following Python script searches through C code for division or sqrt
and prints the line of code and the line number. It skips C comments.
To use, run <code>python find_divides.py filename.c</code>
</p>
<pre class="python">#!/usr/bin/python
"""find_divides.py
usage: python find_divides.py filename
"""
import re
import sys
def main():
filename = sys.argv[1]
text = open(filename).read()
lines = text.splitlines()
lines = ["%4d: %s" % (i, line) for (i, line) in enumerate(lines)]
text = "\n".join(lines)
text = remove_comments_and_strings(text)
for line in text.splitlines():
if ("/" in line) or ("sqrt" in line):
print line
def remove_comments_and_strings(text):
""" remove c-style comments and strings
text: blob of text with comments (can include newlines)
returns: text with comments and strings removed
"""
pattern = r"""
## --------- COMMENT ---------
/\* ## Start of /* ... */ comment
[^*]*\*+ ## Non-* followed by 1-or-more *'s
( ##
[^/*][^*]*\*+ ##
)* ## 0-or-more things which don't start with /
## but do end with '*'
/ ## End of /* ... */ comment
| ## -OR- various things which aren't comments:
( ##
## ------ " ... " STRING ------
" ## Start of " ... " string
( ##
\\. ## Escaped char
| ## -OR-
[^"\\] ## Non "\ characters
)* ##
" ## End of " ... " string
| ## -OR-
##
## ------ ' ... ' STRING ------
' ## Start of ' ... ' string
( ##
\\. ## Escaped char
| ## -OR-
[^'\\] ## Non '\ characters
)* ##
' ## End of ' ... ' string
| ## -OR-
##
## ------ ANYTHING ELSE -------
(. ## Anything other char
[^/"'\\]*) ## Chars which doesn't start a comment, string
) ## or escape
"""
regex = re.compile(pattern, re.VERBOSE|re.MULTILINE|re.DOTALL)
goodstuff = [m.group(5) for m in regex.finditer(text) if m.group(5)]
return "".join(goodstuff)
if __name__ == "__main__":
main()</pre>
Recommended books
2008-04-17T19:13:00-07:00https://www.saltycrane.com/blog/2008/04/recommended-books/<p>I love having a subscription to <a href="http://search.safaribooksonline.com/home">
Safari Books Online</a>. Currently my company provides a free subscription,
but if I get a new job, I might consider subscribing myself. Since I get to
browse a number of books at no cost, I thought I'd note which books are my
favorites. (Note, I am not being paid by Safari Books Online.)</p>
<h4 id="general-software">General Software</h4>
<ul>
<li><em>Structure and Interpretation of Computer Programs, Second Edition</em>,
Harold Abelson and Gerald Jay Sussman, MIT Press, ?year?<br />
I learned about this book through a job posting. It might bring you to
tears if you get it. I'm only in the second chapter. It is used in an introductory
Computer Science course at MIT. It uses Scheme (Lisp) to demonstrate concepts.<br />
Available free online at:
<a href="http://mitpress.mit.edu/sicp/full-text/book/book.html">
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-4.html</a><br />
A <a href="http://swiss.csail.mit.edu/classes/6.001/abelson-sussman-lectures/">
free video lecture series</a> is also available.
</li>
</ul>
<h4 id="c">C</h4>
<ul>
<li><em>The C Programming Language, Second Edition</em>, Brian W. Kernighan
and Dennis M. Ritchie, Prentice Hall, 1988<br />
The definitive C book.
</li>
</ul>
<h4 id="python">Python</h4>
<ul>
<li><em>Core Python Programming, Second Edition</em>, Wesley J. Chun,
Prentice Hall, September 18, 2006<br />
Usually I like O'Reilly books best, but I slightly prefer Chun's text
to <em>Learning Python</em>.<br />
Available at
<a href="http://search.safaribooksonline.com/0132269937?tocview=true">
Safari Books Online</a>
</li>
<li><em>The Django Book</em>, Apress, December 2007<br />
I think this is the first official Django book.<br />
</li>
</ul>
<h4 id="sqlite">SQLite</h4>
<ul>
<li><em>The Definitive Guide to SQLite</em>, Mike Owens, Apress, May 2006<br />
I browsed a few SQL books but liked this one better than most.
It has a good theory section.<br />
Available at
<a href="http://apress.com/book/view/9781590596739">
Apress.com</a>
</li>
</ul>
<h4 id="linux">Linux or related</h4>
<ul>
<li><em>X Power Tools</em>, Chris Tyler, O'Reilly, December 15, 2007<br />
Lots of good information on the X Window System and more; easy to understand.
I wish the basic Ubuntu or
Linux books had some of this information.<br />
Available at
<a href="http://search.safaribooksonline.com/9780596101954?tocview=true">
Safari Books Online</a>
</li>
<li>
<em>SSH, The Secure Shell: The Definitive Guide, Second Edition</em>,
Daniel J. Barrett; Richard E. Silverman; Robert G. Byrnes,
O'Reilly, May 10, 2005<br>
Available at
<a href="http://search.safaribooksonline.com/book/networking/ssh/0596008953">
Safari Books Online</a>
</li>
</ul>
<h4 id="ruby">Ruby</h4>
<ul>
<li><em>why's poignant guide to Ruby</em> by <a href="http://whytheluckystiff.net/">why
the lucky stiff</a><br />
Only in chapter 3, but very funny.<br />
Available free online at: <a href="http://poignantguide.net/ruby/">http://poignantguide.net/ruby/</a>
</li>
</ul>
<h4 id="javascript">Javascript</h4>
<ul>
<li>
<em>Javascript: The Good Parts</em>, Douglas Crockford, O'Reilly, May 2008<br>
This is the first Javascript book I read as I switched to Javascript and Frontend development. I was debating whether to read it since it was so old but I found it to be good and recommend it.
</li>
<li>
<em>You Don't Know JS: ES6 & Beyond</em>, Kyle Simpson, O'Reilly, December 2015<br>
This is the primary way I learned ES6. It is very detail oriented.<br>
Available free online
<a href="https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20%26%20beyond">
on github
</a>
</li>
<li>
<em>JavaScript Allongé, the "Six" Edition</em>, Reg "raganwald" Braithwaite, Leanpub, 2016<br>
This was the third Javascript book I read and it was the most fun. It teaches functional programming concepts such as closures, shadowing, higher order functions, combinators, decorators, etc using ES6.<br>
Available free online at:
<a href="https://leanpub.com/javascriptallongesix/read">https://leanpub.com/javascriptallongesix/read</a>
</li>
</ul>
<h4 id="non-technical">Non technical</h4>
<ul>
<li>The Hitchhiker's Guide to the Galaxy by Douglas Adams</li>
<li>Calvin and Hobbes by Bill Watterson</li>
<li>Crime and Punishment by Fyodor Dostoyevsky</li>
<li>Mere Christianity by C. S. Lewis</li>
<li>Screwtape Letters by C. S. Lewis</li>
</ul>
<h4 id="see-also">See also</h4>
<ul>
<li><a href="http://www.reddit.com/r/books/comments/ch0wt/a_reading_list_for_the_selftaught_computer/">
http://www.reddit.com/r/books/comments/ch0wt/a_reading_list_for_the_selftaught_computer/</a></li>
<li><a href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read">
http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read</a></li>
<li><a href="http://www.reddit.com/r/books/comments/cq4qe/reddits_bookshelf/">
http://www.reddit.com/r/books/comments/cq4qe/reddits_bookshelf/</a></li>
</ul>
How to remove C style comments using Python
2007-11-28T17:25:00-08:00https://www.saltycrane.com/blog/2007/11/remove-c-comments-python/<p>The Perl FAQ has an
entry <a href="http://perldoc.perl.org/perlfaq6.html#How-do-I-use-a-regular-expression-to-strip-C-style-comments-from-a-file%3f">How
do I use a regular expression to strip C style comments from a
file?</a> Since I've switched to Python, I've adapted the Perl
solution to Python. This regular expression was created by Jeffrey Friedl and
later modified by Fred Curtis. I'm not certain, but it
appears to use the "unrolling the loop" technique described in
Chapter 6 of <em>Mastering Regular Expressions</em>.</p>
<p>remove_comments.py:</p>
<pre class="python">import re
import sys
def remove_comments(text):
""" remove c-style comments.
text: blob of text with comments (can include newlines)
returns: text with comments removed
"""
pattern = r"""
## --------- COMMENT ---------
/\* ## Start of /* ... */ comment
[^*]*\*+ ## Non-* followed by 1-or-more *'s
( ##
[^/*][^*]*\*+ ##
)* ## 0-or-more things which don't start with /
## but do end with '*'
/ ## End of /* ... */ comment
| ## -OR- various things which aren't comments:
( ##
## ------ " ... " STRING ------
" ## Start of " ... " string
( ##
\\. ## Escaped char
| ## -OR-
[^"\\] ## Non "\ characters
)* ##
" ## End of " ... " string
| ## -OR-
##
## ------ ' ... ' STRING ------
' ## Start of ' ... ' string
( ##
\\. ## Escaped char
| ## -OR-
[^'\\] ## Non '\ characters
)* ##
' ## End of ' ... ' string
| ## -OR-
##
## ------ ANYTHING ELSE -------
. ## Anything other char
[^/"'\\]* ## Chars which doesn't start a comment, string
) ## or escape
"""
regex = re.compile(pattern, re.VERBOSE|re.MULTILINE|re.DOTALL)
noncomments = [m.group(2) for m in regex.finditer(text) if m.group(2)]
return "".join(noncomments)
if __name__ == '__main__':
filename = sys.argv[1]
code_w_comments = open(filename).read()
code_wo_comments = remove_comments(code_w_comments)
fh = open(filename+".nocomments", "w")
fh.write(code_wo_comments)
fh.close()</pre>
<br>Example:<br>
To test the script, I created a test file called <code>testfile.c</code>:
<pre>/* This is a C-style comment. */
This is not a comment.
/* This is another
* C-style comment.
*/
"This is /* also not a comment */"</pre>
<br>Run the script:<br>
To use the script, I put the script, <code>remove_comments.py</code>,
and my test file, <code>testfile.c</code>, in the same directory and ran the
following command:<br>
<pre>python remove_comments.py testfile.c</pre>
<br>Results:<br>
The script created a new file called <code>testfile.c.nocomments</code>:
<pre>
This is not a comment.
"This is /* also not a comment */"</pre>
<br><br><br>
---------------<br>
Minor note on Perl to Python migration:<br>
I modified the original regular expression comments a little bit.
In particular, I had to put at least one character after the <code>##
Non "\</code> and <code>## Non '\</code> lines because, in Python,
the backslash was escaping the following newline character and the
closing parenthesis on the following line was being treated as a
comment by the regular expression engine. This is the error I got,
before the fix:
<pre>$ python remove_comments.py
Traceback (most recent call last):
File "remove_comments.py", line 39, in <module>
regex = re.compile(pattern, re.VERBOSE|re.MULTILINE|re.DOTALL)
File "C:\Programs\Python25\lib\re.py", line 180, in compile
return _compile(pattern, flags)
File "C:\Programs\Python25\lib\re.py", line 233, in _compile
raise error, v # invalid expression
sre_constants.error: unbalanced parenthesis</pre>
My software tools list
2007-08-10T13:32:00-07:00https://www.saltycrane.com/blog/2007/08/current-configuration/<style type="text/css">
td {
vertical-align: top;
}
</style>
<p>Inspired by Mark Pilgrim's
<a href="http://web.archive.org/web/20101214224709/http://diveintomark.org/archives/2006/06/26/essentials-2006">
2006 Essentials list</a>,
below is a list of my current software tools. If you notice a lot of
"I switched from ..." statements, keep in mind that I am a
<a href="http://undefined.com/ia/2006/10/10/the-fourteen-types-of-programmers-type-2-those-that-like-shiny-things/">
programmer who likes shiny things</a>.
</p>
<h4 id="other-lists">Other lists</h4>
<ul>
<li><a href="http://web.archive.org/web/20101214234142/http://diveintomark.org/archives/2008/10/28/essentials-2008">
Mark Pilgrim's Essentials, 2008 edition</a>
</li>
<li><a href="http://web.archive.org/web/20081226033542/http://adam.gomaa.us/blog/essentials-cop-out/">
Adam Gomaa's Essentials (2008)</a>
</li>
<li>Here is a <a href="http://mark.pilgrim.usesthis.com/">2010 update
for Mark Pilgrim</a>. After 2 and a half years, I still have several items
in common: <a href="#operating-system">Ubuntu</a> running <a href="#terminal">rxvt-unicode</a>
and <a href="#editor">Emacs 23</a>, the <a href="#keyboard">Unicomp keyboard</a>,
an <a href="#mobile-phone">Android phone</a>, <a href="#email">Gmail</a>,
Google Reader, Google Docs, and Pandora.
</li>
<li><a href="http://salvatore.sanfilippo.usesthis.com/">Salvatore Sanfilippo on usesthis.com (2011)</a></li>
<li><a href="http://aaron.boodman.usesthis.com/">Aaron Boodman on usesthis.com (2011)</a></li>
</ul>
<h4 id="contents">Contents</h4>
<table>
<tr>
<td>
<ul>
<li><a href="#operating-system">Operating System</a>: Ubuntu</li>
<li><a href="#window-manager">Window Manager</a>: Qtile</li>
<li><a href="#editor">Editor</a>: Emacs</li>
<li><a href="#terminal">Terminal</a>: urxvt + screen</li>
<li><a href="#vcs">Version Control System</a>: Git</li>
<li><a href="#high-high-level-language">"High-high-level" Language</a>: Python</li>
<li><a href="#web-framework">Web Framework</a>: Django/Flask</li>
</ul>
</td>
<td>
<ul>
<li><a href="#web-browser">Web Browser</a>: Firefox</li>
<li><a href="#email">Email</a>: Gmail</li>
<li><a href="#graphical-diff">Graphical Diff</a>: KDiff3</li>
<li><a href="#keyboard">Keyboard</a>: Leopold Tenkeyless (MX Browns)</li>
<li><a href="#office-chair">Office Chair</a>: Undecided</li>
<li><a href="#mobile-phone">Mobile Phone</a>: Motorola Droid 4</li>
</ul>
</td>
</tr>
</table>
<h4 id="my-list">My software tools list</h4>
<table style="font-size:100%">
<tr>
<td ><b>Category</b></td>
<td ><b>Currently using</b></td>
<td ><b>Comments</b></td>
</tr>
<tr>
<td id="operating-system" ><p>Operating System</p>
<a href="#operating-system" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.ubuntu.com">Ubuntu</a> 14.04 Trusty Tahr</p>
</td>
<td >
<p>My first
Ubuntu install was in 2007 (dual-boot) and I got my first Windows-free machine
in 2008. I have used Cygwin
and coLinux when on Windows. Cygwin integrates better with Windows applications,
but coLinux is super fast and allows you to run a full Linux distro on top of
Windows. Windows does have some advantages, but overall I prefer Linux.</p>
<p><em>Update 2008-09</em>: Switching jobs means I can now use Linux at work.
I'm now using Linux about 90% of the time. My wife still uses Windows Vista on our laptop.</p>
<p>I don't have enough experience
with OSX to draw any authoritative conclusions, though I think
<a href="http://en.wikipedia.org/wiki/Mark_Pilgrim">Mark Pilgrim</a>
has <a href="http://diveintomark.org/archives/2006/06/02/when-the-bough-breaks">
biased me against Apple</a>. Also, I think Linux's
<a href="http://c2.com/cgi/wiki?FreeAsInBeer">free as in beer</a> (and somewhat
related free as in speech) characteristics
vs. Mac's expensive (and somewhat related proprietary) characteristics
resonate with the cheap engineer in me.</p>
<p>Additional Linux vs. Mac commentary:</p>
<ul>
<li>
<a href="http://en.wikipedia.org/wiki/Jamie_Zawinski">JWZ</a> 2000:
<a href="http://www.jwz.org/doc/linux.html">Unix/linux sucks less, but it still sucks.</a>
</li>
<li>
JWZ <a href="http://jwz.livejournal.com/494040.html">2005</a>,
<a href="http://jwz.livejournal.com/780264.html">2007</a>: Linux sucks more.
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Paul_Graham">Paul Graham</a> 2005:
<a href="http://www.paulgraham.com/mac.html">Return of the Mac.</a>
</li>
<li>
Mark Pilgrim 2006: <a href="http://diveintomark.org/archives/2006/05/30/bye-apple">
Bye, Apple</a>
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Cory_Doctorow">Cory Doctorow</a> 2006:
<a href="http://www.boingboing.net/2006/06/29/mark-pilgrims-list-o.html">
Me too</a>.
</li>
<li>
<a href="http://en.wikipedia.org/wiki/Tim_Bray">Tim Bray</a> 2006:
<a href="http://www.tbray.org/ongoing/When/200x/2006/06/15/Switch-From-Mac">Me too</a>,
<a href="http://www.tbray.org/ongoing/When/200x/2006/08/16/Back-to-the-Mac">Back to the Mac</a>
</li>
<li>
Steve Yegge 2008:
<a href="http://steve-yegge.blogspot.com/2008/04/settling-osx-focus-follows-mouse-debate.html">
Switching to OSX for the fonts</a>
</li>
<li>
Of course, <a href="http://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a>
<a href="http://www.smh.com.au/news/technology/q-and-a-with-linus-torvalds/2008/02/05/1202090403120.html?page=2">
"prefers" Linux</a> (2008)
</li>
<li><a href="http://en.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a>,
author of <em>The Art of Computer Programming</em>,
<a href="http://www.informit.com/articles/printerfriendly.aspx?p=1193856">
uses Ubuntu Linux for work, and Macs for play</a> (2008).
</li>
<li>Salvatore Sanfilippo (author of <a href="http://code.google.com/p/redis/">Redis</a>)
chooses to use
a Mac so he can <em>"focus on what <he's> doing without spending hours trying to
fix unrelated desktop stuff"</em> but says Linux is
<a href="http://antirez.com/post/linux-better-for-coding.html">
<em>"still better for coding"</em></a> (2009).
</li>
<li>Ted Dziuba: <a href="http://harmful.cat-v.org/software/operating-systems/osx/osx-unsuitable-web-development">
<em>MacOS X is an Unsuitable Platform for Web Development</em>
</a> (2011)</li>
<li>Bozhidar Batsov: <a href="http://batsov.com/Linux/Windows/Rant/2011/06/11/linux-desktop-experience-killing-linux-on-the-desktop.html">
<em>The Linux desktop experience is killing Linux on the desktop</em>
</a> (2011)</li>
</ul>
<p>History: 1987: <a href="http://en.wikipedia.org/wiki/Apple_IIGS">Apple GS/OS</a>,
1994: <a href="http://en.wikipedia.org/wiki/Windows_3.1x">Windows 3.1</a>,
2000: <a href="http://en.wikipedia.org/wiki/Windows_98">Windows 98</a>,
2001: <a href="http://en.wikipedia.org/wiki/Windows_XP">Windows XP</a>,
2007: <a href="http://en.wikipedia.org/wiki/Windows_Vista">Windows Vista</a>,
2007: <a href="http://en.wikipedia.org/wiki/Ubuntu_%28operating_system%29">Ubuntu</a>
</p>
</td>
</tr>
<tr>
<td id="window-manager"><p>Window Manager</p>
<a href="#window-manager" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.qtile.org/">Qtile</a></p></td>
<td >
<p>The WM written in Python,
<a href="http://panela.blog-city.com/fun_of_tiling_window_managers.htm">
recommended by Matt Harrison</a>.
</p>
<p>Previously, wmii: dynamic, tiling, scriptable window manager that doesn't
require a mouse. It sucks less.</p>
<p>I switched from <a href="http://www.nongnu.org/ratpoison/">ratpoison</a>
at the same time I started using coLinux because running native Linux
allowed me to use any Linux window manager as well.</p>
<p>Recently, some have switched from wmii to
<a href="http://xmonad.org/">xmonad</a>, the new
<a href="http://www.haskell.org/">Haskell</a> tiling window manager.
It has some nice features over wmii, including dual head support, but after
a brief excursion, I slightly prefer wmii's way of doing things.</p>
<p>If you're a hard core Lisper,
<a href="http://www.nongnu.org/stumpwm/">stumpwm</a> is the window manager
for you. It has a <a href="http://en.wikipedia.org/wiki/REPL">REPL</a>. This one
seems a little too hard core for me, especially since I don't know Lisp.</p>
<p>History: 2007: ratpoison, 2007: wmii, 2012: Qtile</p>
</td>
</tr>
<tr>
<td id="editor"><p>Editor/IDE</p>
<a href="#editor" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://www.gnu.org/software/emacs">GNU Emacs</a> 24.3</p></td>
<td >
<p>Switched from Eclipse in 2007. It was a slow transition, but
I think Emacs is worth the investment.</p>
<p><b>On Emacs vs. Vim:</b> I really like that Vim can be used easily on remote
machines. Currently, I use TRAMP for remote file editing. It is very cool,
but it is slow, and I sometimes fall back on nano (*gasp*) for a quick
config file edit when I am logged into a remote terminal. I also suspect
that the dual modes of Vim are more efficient than Emacs-- I'm just not
smart enough to get used to it. Maybe someday I will switch to
<a href="http://www.gnu.org/software/emacs/manual/html_node/viper/index.html#Top">Viper
mode</a>. Why Emacs over Vim? I choose Emacs because it is more powerful
and closer to an IDE. Emacs Lisp allows you to do whatever you want.
</p>
<p><b>On Emacs vs. Eclipse:</b> I found Eclipse was too slow and heavy, used too
much screen real estate, and was too difficult to customize. Scripting
Eclipse required writing extensions in Java whereas Emacs can be extended
in elegant Lisp. I think Eclipse (and other IDE's) are better for code
exploration and they probably have features that I'm not aware of since
I don't use them. I figure, though, that with enough Emacs Lisp, Emacs
can do anything those IDEs can do. If you really want those features,
it's a question of if you want to spend the time achieving perfection
in Emacs or getting real work done in another IDE. I choose perfection. ;)
</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://blog.ianbicking.org/the-vs-emacs.html">
THE vs. Emacs</a>, Ian Bicking (2005)</li>
<li><a href="http://steve.yegge.googlepages.com/effective-emacs">
Effective Emacs</a>, Steve Yegge (2005)</li>
<li><a href="http://blog.ianbicking.org/other-editors.html">
Other Editors?</a>, Ian Bicking (2005)</li>
<li><a href="http://glyph.twistedmatrix.com/2008/04/structured-python-editor.html">
Structured Python Editor</a>, Glyph Lefkowitz (2008)</li>
<li><a href="http://chalain.livejournal.com/74234.html">
Editor Wars: Revenge of the... oh, whatever.</a>, Chalain (2008)</li>
<li><a href="http://metajack.im/2008/09/05/what-you-can-learn-from-emacs/">
What You Can Learn From Emacs</a>, Jack Moffitt (2008)</li>
<li><a href="http://glyph.twistedmatrix.com/2008/12/emacs-test.html">
The Emacs Test</a>, Glyph Lefkowitz (2008)</li>
<li><a href="http://www.redreddesign.com/blog/emacs-extensions-i-cant-live-without/">
emacs extensions i can’t live without</a> (2009)</li>
</ul>
<p>Screencasts:</p>
<ul>
<li><a href="http://platypope.org/yada/emacs-demo/">I need a cool European accent</a></li>
<li><a href="http://www.vimeo.com/1013263">What You Can Learn From ido.el</a></li>
<li><a href="http://www.youtube.com/watch?v=76Ygeg9miao#t=01m47s">YASnippet demo</a></li>
</ul>
<p>Install method:
<del><a href="http://www.saltycrane.com/blog/2008/10/installing-emacs-23-cvs-ubuntu-hardy/">
from source</a></del>
<code>sudo apt-get install emacs</code>
</p>
<p>Useful packages:</p>
<ul>
<li><a href="http://www.gnu.org/software/tramp/">
Tramp</a>: transparent remote file access</li>
<li><a href="http://www.emacswiki.org/emacs/InteractivelyDoThings">
ido</a>: Buffer switching and more</li>
<li><a href="http://orgmode.org/">Org-Mode</a>: note taking, task lists</li>
<li><a href="http://github.com/yoshiki/yaml-mode">yaml-mode</a>: for yaml</li>
<li><a href="http://jblevins.org/projects/markdown-mode/">markdown-mode</a>: for markdown</li>
<li><a href="http://code.google.com/p/yasnippet/">YASnippet</a>:
Textmate-inspired templating. Great for making HTML less tedious.</li>
<li><a href="https://github.com/nonsequitur/smex">smex: IDO for M-x</a></li>
<li><a href="https://github.com/magnars/multiple-cursors.el">multiple-cursors</a>: this is really fun *and* useful.</li>
<li><a href="http://web-mode.org/">web-mode</a>: for HTML/CSS/Javascript</li>
</ul>
<p>My emacs config on github: <a href="http://github.com/saltycrane/emacs">http://github.com/saltycrane/emacs</a></p>
<p>History: 2001: Emacs/NEdit/UltraEdit, 2006: Eclipse, 2007: Emacs</p>
</td>
</tr>
<tr>
<td id="terminal"><p>Terminal</p>
<a href="#terminal" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://software.schmorp.de/pkg/rxvt-unicode.html">urxvt</a></p>
9.19
+ <br><a href="http://www.gnu.org/software/screen/">screen</a></td>
<td>
<p>urxvt supports xft (anti-aliased) fonts, real transparency (not that
I actually use transparency with Qtile), and fading (which I do use with Qtile)
and it is much faster and lighter than gnome-terminal or konsole. screen allows me to switch
terminal sessions without ugly tabs, attach to remote sessions, search through
the scrollback buffer, and more. <em>Update:</em> urxvt also has embedded perl.</p>
<p>Install method:
<del><a href="/blog/2009/11/how-make-urxvt-look-gnome-terminal/">from source</a></del>
<code>sudo apt-get install rxvt-unicode</code>
</p>
</td>
</tr>
<tr>
<td id="vcs"><p>Version Control System</p>
<a href="#vcs" title="Section permalink" class="sectionlink">¶</a></td>
<td>
<p><a href="http://git-scm.com/">Git</a></p>
</td>
<td>
<p>Switched from Subversion to Mercurial in June 2007. The merging in Mercurial
is very nice and can be done without thinking. I do miss Subversion/Subclipse's
revision history viewer, file compare, and ability to isolate files apart from
changesets. <em>Update 2010-04-05:</em> See <a href="#c8633">my comment
below</a>.
</p>
<p><em>Update 2011-05:</em> Switched my personal repos to Git. Use Git almost
exclusively now.
</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://jonchu.posterous.com/16445171">
DVCS: Why I chose Mercurial over Git</a> (2010)</li>
<li><a href="http://blog.extracheese.org/2010/05/why-i-switched-to-git-from-mercurial.html">
Why I Switched to Git From Mercurial</a> (2010)</li>
</ul>
<p>Install method: <code>sudo apt-get install mercurial</code></p>
<p>History: 2001: SCCS, 2003: Other, 2007: Subversion, 2007: Mercurial,
2010: Mercurial/Git, 2011: Git</p>
</td>
</tr>
<tr>
<td id="high-level-language"><p>"High-level" Language</p>
<a href="#high-level-language" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>None</p></td>
<td>
<p>Previously, I used C. Now I use don't use any statically-typed languague. Wouldn't mind learning <del>C++</del> Go. Although,
Linus <a href="http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918">
doesn't like it.</a></p>
</td>
</tr>
<tr>
<td id="high-high-level-language" ><p>"High-high-level" Language</p>
<a href="#high-high-level-language" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://www.python.org/">Python</a> 2.7</p></td>
<td >
<p>My love for Python is strong. I switched from Perl in 2005
and have no regrets. Object-oriented, easy to read (no more
<a href="http://en.wikipedia.org/wiki/There_is_more_than_one_way_to_do_it">
TIMTOWTDI</a>), and smart people use it. I also want to learn Javascript 2
becuase it is the
<a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html">
"Next Big Language"</a> and Lisp because it is the
<a href="http://www.paulgraham.com/avg.html">"most powerful language"</a>.</p>
<p><b>On Python vs. Ruby:</b> from what I've read, I characterize Ruby as the
more expressive language more similar to Perl (than Python is) and Python
as the more regimented language. Since I like regimented, I like Python.</p>
<p><b>On Python vs. Lisp:</b> I've concluded that I lack the intelligence to
harness enough of Lisp's power to counteract its non-practicality (e.g.
lack of libraries).</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Paul_Graham">Paul Graham</a>:
<a href="http://www.paulgraham.com/icad.html">Python is
getting closer to Lisp</a> (2002)</li>
<li>Paul Prescod: <a href="http://www.prescod.net/python/IsPythonLisp.html">
no it isn't</a></li>
<li>Paraphrase of <a href="http://www.swiss.ai.mit.edu/~gjs/">
Gerald Jay Sussman</a> (one of the creators of Scheme):
<a href="http://blog.snowtide.com/2009/03/24/why-mit-now-uses-python-instead-of-scheme-for-its-undergraduate-cs-program">
Why MIT now uses python instead of scheme for its undergraduate CS program</a>
(2009)</li>
</ul>
<p>Install method: preinstalled on Ubuntu</p>
<p>History: 2001: <a href="http://www.perl.org/">Perl</a>,
2005: <a href="http://www.python.org/">Python</a>
</p>
</td>
</tr>
<tr>
<td id="web-framework" ><p>Web Framework</p>
<a href="#web-framework" title="Section permalink" class="sectionlink">¶</a></td>
<td >
<p>
<a href="http://www.djangoproject.com/">Django</a> /
<a href="http://flask.pocoo.org/">Flask</a>
</p>
</td>
<td >
<p><em>2014-10:</em>I now use Flask at work. Previously, I used Django. I think I like SQLAlchemy and Jinja2 better than Django. Django has a lot more built in and is put together better. Flask's thread locals are convenient and messy. Probably <a href="http://www.pylonsproject.org/">Pyramid</a> is the best but no one uses it.</p>
<p>Here are some links:</p>
<ul>
<li><a href="http://www.ianbicking.org/">Ian Bicking</a>:
<a href="http://blog.ianbicking.org/theres-so-much-more-than-rails.html">
There's so much more than Rails</a> (2005)</li>
<li><a href="http://blog.ianbicking.org/2008/01/12/what-php-deployment-gets-right/">
What PHP deployment gets right</a> (2008)</li>
<li><a href="http://www.feedmagnet.com/blog/django-vs-rails/">
Django vs. Rails</a> (2009)</li>
</ul>
<p>Install method: <code>pip install Django</code> / <code>pip install Flask</code></p>
</td>
</tr>
<tr>
<td id="web-browser"><p>Web Browser</p>
<a href="#web-browser" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>Firefox</p></td>
<td >
<p>Not to be confused with <a href="http://www.konqueror.org">
Konqueror</a>, Conkeror is an emacs-like, keyboard driven, scriptable,
Mozilla-based web browser. I've used it almost full
time since January 2008. It is still considered alpha stage software
so there are a number of bugs. However, it is still pretty sweet. I use
Firefox as a backup (and IE Tab for Launchcast and Netflix on Windows).</p>
<p>Unfortunately, one of the annoying things in Firefox 2 is present in
Conkeror as well-- memory leaks. Based on
<a href="http://kb.mozillazine.org/Memory_Leak">this Mozilla article</a>
and some brief personal experience, Firefox 3 has made fixes in this area.
It would be nice if Conkeror could benefit from the Firefox 3 fixes.</p>
<p><em>Update 2010-05-04:</em> Conkeror is really awesome, but I had some memory/cpu issues with it
a while ago and haven't put in the work to merge my custom keybindings
with the latest Conkeror code. Also waiting to see if there will be
an Emacs version of <a href="http://vimium.github.com/">Vimium</a>
(since, after all <a href="http://vimperator.org/">vimperator</a>
followed conkeror).
</p>
<p>I'm currently using a combination of Google Chrome and Firefox.
Chrome is faster, especially for Javascript-intensive sites, but I really
<a href="http://superuser.com/questions/91334/alternative-to-arrow-keys-in-google-chrome-location-bar">
<em>hate</em> the Google Chrome Omnibar</a>. If you have a solution
or workaround, please post an answer. Firefox also has some Add-ons
that Chrome doesn't.
</td>
</tr>
<tr>
<td id="email" ><p>Email</p>
<a href="#email" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p>Gmail</p></td>
<td >
<p><em>Update 2010-05-04:</em>
Gmail. It's slow but it has a lot of features and it's in
my web browser and it's easy and it works and I don't really like using
email that much anyways. Oh, and, big plus, syncing works almost perfect
with my Android phone. (Actual full switch to Gmail was around December 2008.)
</p>
</td>
</tr>
<tr>
<td id="graphical-diff" ><p>Graphical diff/merge</p>
<a href="#graphical-diff" title="Section permalink" class="sectionlink">¶</a></td>
<td ><p><a href="http://kdiff3.sourceforge.net/">KDiff3</a></p></td>
<td >
<p>I started using KDiff a while ago on Windows and have
always liked it. I'm thinking, though, since I'm an Emacs person, I ought to
use <a href="http://www.gnu.org/software/emacs/manual/html_mono/ediff.html">
Ediff</a>.</p>
<p>Install method: <code>sudo apt-get install kdiff3</code></p>
</td>
</tr>
<tr>
<td id="keyboard"><p>Keyboard</p>
<a href="#keyboard" title="Section permalink" class="sectionlink">¶</a></td>
<td>
<p><a href="http://pckeyboards.stores.yahoo.net//en104wh.html">
Unicomp Endurapro</a> /
<a href="http://elitekeyboards.com/products.php?sub=leopold,tenkeyless&pid=fc200rtab">
Leopold Tenkeyless w/ Cherry MX Browns
</a></p>
</td>
<td>
<p>I realize a keyboard is hardware and not software, but it is
hardware that can evoke strong opinions, so I made an exception.
</p>
<p>One problem with hardware is I can't try out all the different types
and choose the one I like the best as I can with software. So
my selection is based on reviews not on actual experience. And,
after buying the Endurapro, I found I actually did not like the
integrated mouse stick, so I should have bought a Customizer 104/105
and saved $30.</p>
<p><em>Update 2011-05:</em> Got the Leopold tenkeyless for work.
Tenkeyless is a must for quicker mouse access.
And I actually like the lighter touch of the
Cherry MX Browns versus the Unicomp's buckling springs. I like it
so much I want to replace my Unicomp at home with another Leopold.
</p>
<p><em>Update:</em> Got a second Leopold for home to replace my Unicomp.</p>
<p>Additional commentary:</p>
<ul>
<li><a href="http://www.jwz.org/gruntle/wrists.html">
my wrists and welcome to them.</a>, JWZ (1999)</li>
<li><a href="http://www.dansdata.com/deck.htm">
Deck keyboard</a>, Dan (2005)</li>
<li><a href="http://bc.tech.coop/blog/060131.html">
Surviving Emacs - Part 4</a>, Bill Clementson (2006)</li>
<li><a href="http://glyf.livejournal.com/55780.html">
Keyboard Fight</a>, Glyph Lefkowitz (2006)</li>
<li><a href="http://diveintomark.org/archives/2006/05/30/bye-apple">
Bye, Apple</a>, Mark Pilgrim (2006)</li>
<li><a href="http://glyph.twistedmatrix.com/2009/01/meandering-review-of-logitech.html">
A Meandering Review of the Logitech Illuminated Keyboard</a>,
Glyph Lefkowitz (2009)</li>
</ul>
<p>History: 2009: Unicomp Endurapro, 2011: Leopold Tenkeyless (MX Browns)</p>
</td>
</tr>
<tr>
<td id="office-chair"><p>Office Chair</p>
<a href="#office-chair" title="Section permalink" class="sectionlink">¶</a></td>
<td><p>Undecided</p></td>
<td><p>Herman Miller Aeron or Steelcase Leap</p>
</td>
</tr>
<tr>
<td id="mobile-phone"><p>Mobile Phone</p>
<a href="#mobile-phone" title="Section permalink" class="sectionlink">¶</a></td>
<td><p><a href="http://www.motorola.com/Consumers/US-EN/Consumer-Product-and-Services/Mobile-Phones/Motorola-DROID-US-EN">Motorola Droid 4</a></p></td>
<td>
<p>After almost 10 years (and 3 generations) of the Palm Treo, I got the
Motorola Droid.</p>
<p>The Droid is pretty awesome, but I don't like switching
to landscape mode to use the keyboard-- especially when toolbars and headers
take up half the screen. I think Palm and Blackberry got this form factor Right.
Just as I prefer the keyboard over the mouse on my PC, I want to use the keyboard
and D-pad over the touchscreen on my phone.
<em>Update 2010-05-04:</em> The keyboard is mediocre and use of the D-pad
center button sucks. My Palm Treo 650 D-pad worked much better.
</p>
<p>My reasons for choosing an
<a href="http://en.wikipedia.org/wiki/Android_%28operating_system%29">Android</a>
phone are: I <em>need</em> a physical keyboard.
I <em>want</em> to hack on my phone. I <em>think</em> Android has more potential than Palm's
<a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>
or <a href="http://en.wikipedia.org/wiki/Maemo">Maemo</a>.</p>
<p>Useful apps:</p>
<ul>
<li><a href="http://code.google.com/p/connectbot/">Connectbot</a>
Secure shell (SSH) client for the Android platform. Use this all the time. Awesome.</li>
<li><a href="http://www.android.com/market/#app=listen">Listen</a>
Listen from Google Labs brings podcast search, subscribe, download and stream to your Android-powered device.</li>
<li><a href="http://mytracks.appspot.com/">My Tracks</a>
Record GPS tracks. Monitor your performance. Share your outdoor activities with friends.
Really enjoy this one. Love tracking my romping.
</li>
</ul>
<p><em>2010-05-04 Updates:</em></p>
<ul>
<li><a href="http://www.google.com/mobile/voice/">Google Voice</a>: Free text messages
and better voicemail. Another useful app. Makes voicemail suck a lot less.</li>
<li><a href="http://levelupstudio.com/foxyring">FoxyRing</a>: automatically
control the ringer volume based on ambient noise level. I was doubtful about this one,
but it actually works well for me.</li>
<li><a href="http://www.flixster.com/mobile/apps/android">Flixter (Movies)</a>:
Useful for checking movie showtimes.
</li>
<li><a href="http://www.youversion.com/mobile/android">Bible (YouVersion)</a>:
This version is pretty good. I miss my <a href="http://www.plkr.org/">Plucker</a>
created Bible on my Palm though. I wish there was something like Plucker for
Android.
</li>
<li>DroidLight: use the LED camera flash as a flashlight. Simple and useful.
Works much better than using the screen as a flashlight.
</li>
<li><a href="http://www.google.com/mobile/navigation/">Google Navigation</a>: I
don't need my Garmin anymore. (Each has advantages and disadvantages, but I
have found it to be a capable replacement.)</li>
<li>Just want to mention that the Calendar sucks. It is great that I can sync
with my Google calendar, but I really hate the Android Calendar UI.</li>
</ul>
<p>Additional Commentary/Links:</p>
<ul>
<li><a href="http://randomfoo.net/2009/06/15/thoughts-on-the-palm-pre-g2-and-iphone-3g">
Thoughts on the Palm Pre, G2, and iPhone 3G</a> Leonard Lin (2009 June)</li>
<li><a href="http://jwz.livejournal.com/1055120.html">
JWZ gets a Palm Pre</a> (2009 June)</li>
<li><a href="http://jwz.livejournal.com/1055369.html">
Emacs on Android</a> (2009 June)</li>
<li><a href="http://daringfireball.net/2009/08/the_android_opportunity">
The Android Opportunity</a>, John Gruber (2009 August)</li>
<li><a href="http://jwz.livejournal.com/1108212.html">
Dear Palm, it's just not working out</a>, JWZ (2009 October)</li>
</ul>
<p>History: 2002: <a href="http://en.wikipedia.org/wiki/Treo_180">Handspring Treo 180</a>,
2003: <a href="http://en.wikipedia.org/wiki/Treo_600">Handspring Treo 600</a>,
2005: <a href="http://en.wikipedia.org/wiki/Treo_650">Palm Treo 650</a>,
2009: <a href="http://en.wikipedia.org/wiki/Motorola_Droid">Motorola Droid</a>
2011: <a href="http://en.wikipedia.org/wiki/Droid_4">Motorola Droid 4</a>
</p>
</td>
</tr>
</table>
Data hiding in C, an object-oriented technique
2007-04-04T11:49:00-07:00https://www.saltycrane.com/blog/2007/04/data-hiding-in-c-object-oriented/<span style="font-family:arial; font-size:small; color:black;">
I am working on some legacy code which uses almost entirely global variables. My task is to change the scope of the variables that don't need to be global. I have changed many of the variables to function scope because they are not used elsewhere, however there is a lot of data that is shared among functions.<br /><br />
My first idea was to create data structures of the shared data and pass pointers to those structures through the parameter list of the functions. However I had some multi-layer function calls. I.e., function1 calls function2 which calls function3. Only the last function called needed the shared data, but the parameter needed to be passed among many functions.<br /><br />
After looking over some other code, I got the idea for using "get" and "set" functions as used in object-oriented programming to access the data structures. The data structures are defined as static at the file scope. The file is like an object with functions that operate on the static data. External (outside the file) access to the data is only allowed through external interface functions declared in a header file which get and set the data.
Here is a simple example with an accessor "get" function which passes a pointer to the static structure. It is declared as a pointer to a pointer because I need to pass the pointer by reference so it can be modified. However the structure itself is declared const so that the accessor won't change the data by mistake. To summarize, it is a pointer to a const structure passed by reference.<br /><br />
main.c:<br />
</span><pre>#include <stdio.h>
#include "algorithm.h"
int main(void)
{
const ALGORITHM_DATA *alg_ptr;
Algorithm();
GetAlgorithmData(&alg;_ptr);
/*alg_ptr->data1 = 99.9;*/ /* This is illegal */
printf("%f\n", alg_ptr->data1);
printf("%f\n", alg_ptr->data2);
printf("%f\n", alg_ptr->data3);
return 0;
}</stdio.h></pre>
algorithm.c:<br />
<pre>#include "algorithm.h"
static ALGORITHM_DATA alg;
void GetAlgorithmData(const ALGORITHM_DATA **out)
{
*out = &alg;
}
void Algorithm(void)
{
alg.data1 = 1.0;
alg.data2 = 2.0;
alg.data2 = 3.0;
}</pre>
algorithm.h:<br />
<pre>#ifndef ALGORITHM_H_
#define ALGORITHM_H_
typedef struct {
double data1;
double data2;
double data3;
} ALGORITHM_DATA;
void GetAlgorithmData(const ALGORITHM_DATA **out);
void Algorithm(void);
#endif /*ALGORITHM_H_*/</pre>
How to share non-global C data structures
2007-02-27T14:36:00-08:00https://www.saltycrane.com/blog/2007/02/how-to-share-non-global-c-data/<span style="font-family:arial; font-size:small; color:black;">
My goal is to share C data structures without using
global variables. I have one function that will fill the data
structure and other functions that will use and optionally
modify the data. I would also like the data structure definition
to be in the same file as the function that fills it. (It looks
like this last requirement requires pointers to pointers and a
malloc so I will abandon it. See <a href="http://groups.google.com/group/comp.lang.c/browse_thread/thread/f58e9acb03205c61/3ff77e7d5456a53f?lnk=gst&q=passing+structure+function&rnum=6#3ff77e7d5456a53f">this thread</a>
in the comp.lang.c newsgroup.)<br /><br />
My solution is to pass pointers to structures to functions as described here:
<a href="http://irc.essex.ac.uk/www.iota-six.co.uk/c/h4_structs_part_3.asp">http://irc.essex.ac.uk/www.iota-six.co.uk/c/h4_structs_part_3.asp</a>
Here is my implementation and notes:<br /><br />
<b>main.c:</b><br />
main.c contains the main function which calls the other functions that operate
on the data structure. It also defines (allocates memory) for the data
structure at the file level. The data structure is declared using the
<code>static</code> keyword so that it will have static duration (i.e. it will exist from
program start to finish), but it will have internal linkage
(i.e. it won't be global). (For more information on declarations
see <a href="http://www-ccs.ucsd.edu/c/declare.html">http://www-ccs.ucsd.edu/c/declare.html</a>
The address operator, <code>&</code>, is used to create a pointer to the
data structure which is passed to the other functions.<br />
</span><pre>#include "defs.h"
#include "get_data.h"
#include "use_data.h"
static DATA data;
int main()
{
get_data(&data;);
modify_data(&data;);
display_data(&data;);
return 0;
}</pre>
<b>defs.h:</b><br />
defs.h contains the combined structure data type declaration and typedef
declaration to create the new type name, <code>DATA</code>. (See <a href="http://www.saltycrane.com/blog/2007/02/notes-on-struct-and-typedef/">
my notes on struct and typedef</a>.) It is included in all the files that
declare the data structure or a pointer to the data structure.<br />
<pre>#ifndef DEFS_H_
#define DEFS_H_
typedef struct
{
int item1;
int item2;
float item3;
float item4;
} DATA;
#endif /*DEFS_H_*/</pre>
<b>get_data.c:</b><br />
get_data.c contains the function to initially fill the data structure. It
is passed a pointer to the data structure defined in main.c. It uses the
structure pointer operator, <code>-></code>, to access the members of the
structure pointed to by <code>data_ptr</code>. <code>data_ptr</code> is
the only local variable in this function-- the data structure being filled
is the same one that was defined in main.c.<br />
<pre>#include "defs.h"
int get_data(DATA *data_ptr)
{
data_ptr->item1 = 1;
data_ptr->item2 = 2;
data_ptr->item3 = 3.0;
data_ptr->item4 = 4.0;
return 0;
}</pre>
<b>use_data.c:</b><br />
use_data.c contains the functions that use and modify the data in the
data structure. They are both passed a pointer to the structure similar
to get_data.c.
<pre>#include <stdio.h>
#include "defs.h"
int modify_data(DATA *data_ptr)
{
data_ptr->item2 += 1;
data_ptr->item4 += 1.0;
return 0;
}
int display_data(DATA *data_ptr)
{
printf("data.item1: %d\n", data_ptr->item1);
printf("data.item2: %d\n", data_ptr->item2);
printf("data.item3: %f\n", data_ptr->item3);
printf("data.item4: %f\n", data_ptr->item4);
return 0;
}</stdio.h></pre>
<b>get_data.h</b><br />
get_data.h and use_data.h contain the function declarations (function
prototypes) and should be included wherever the functions are used.<br />
<pre>#ifndef GET_DATA_H_
#define GET_DATA_H_
int get_data(DATA *data_ptr);
#endif /*GET_DATA_H_*/</pre>
<b>use_data.h</b><br />
<pre>#ifndef USE_DATA_H_
#define USE_DATA_H_
int modify_data(DATA *data_ptr);
int display_data(DATA *data_ptr);
#endif /*USE_DATA_H_*/</pre>
<b>Output:</b><br />
Running the program produces the following output:<br />
<pre>data.item1: 1
data.item2: 3
data.item3: 3.000000
data.item4: 5.000000</pre>
<b>Other notes:</b><br />
Header files should only contain declarations. They should not contain
variable definitions because if the header file is included in multiple
locations there would be multiple definitons of the same variable. (See
<a href="http://groups.google.com/group/comp.lang.c/browse_thread/thread/f85a67ee55a81762/e3037e47972a4b92?lnk=gst&q=define+declare+variable+extern&rnum=2&hl=en#e3037e47972a4b92">
this thread</a> in the comp.lang.c newsgroup.)<br />
<br />
<b>Diagram:
</b><br />
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lZhqNsiakm4/Reh26hy-JHI/AAAAAAAAAAk/wvyV3Yx8gSs/s1600-h/gif_1.gif"><img style="cursor: pointer;" src="http://bp2.blogger.com/_lZhqNsiakm4/Reh26hy-JHI/AAAAAAAAAAk/wvyV3Yx8gSs/s200/gif_1.gif" alt="" id="BLOGGER_PHOTO_ID_5037406931090547826" border="0" /></a><br /><br />
Revision 2 based on comments from <a href="http://groups.google.com/group/comp.lang.c/browse_thread/thread/e488d74fb9b4c13b/dd7c0d07198d9164#dd7c0d07198d9164">this thread</a> on the comp.lang.c newsgroup:<br />
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_lZhqNsiakm4/RezJubUauVI/AAAAAAAAAA4/nYIxnx9E1Z8/s1600-h/png_1.png"><img style="cursor: pointer;" src="http://bp1.blogger.com/_lZhqNsiakm4/RezJubUauVI/AAAAAAAAAA4/nYIxnx9E1Z8/s200/png_1.png" alt="" id="BLOGGER_PHOTO_ID_5038623882565302610" border="0" /></a><br /><br />
Revision 3: Updated based on more comments from the newsgroup. Also, I think my original #includes were OK.<br />
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_lZhqNsiakm4/RfiXMaHYcRI/AAAAAAAAABA/rMENjvKVD78/s1600-h/png_1.png"><img style="cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_lZhqNsiakm4/RfiXMaHYcRI/AAAAAAAAABA/rMENjvKVD78/s200/png_1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5041946022265778450" /></a>
Notes on typedef and struct
2007-02-26T11:49:00-08:00https://www.saltycrane.com/blog/2007/02/notes-on-struct-and-typedef/<span style="font-family:arial; font-size:small; color:black;">
Here are my notes on using C's <code>struct</code> and
<code>typedef</code> keywords.<br /><br />
<h3>struct</h3>
To create a C structure, first create a new structure type:<br />
</span><pre>struct my_struct_tag
{
int member1;
float member2;
};</pre>
Note that in the example above, the <code>struct</code> keyword is used only to
create a new data type but it has not defined any variables yet.<br /><br />
To define new varaibles of this structure type, do this:<br />
<pre>struct my_struct_tag mystruct1;
struct my_struct_tag mystruct2;</pre>
<br />
You can optionally combine these two steps and create the new data type and
define variables:<br />
<pre>struct my_struct_tag
{
int member1;
float member2;
} mystruct1, mystruct2;</pre>
In this case the structure tag <code>my_struct_tag</code> is optional.<br />
<br />
<h3>typedef</h3>
From the K&R; book, the <code>typedef</code> keyword is used to create new data type names. For example:<br />
<pre>typedef int Length;</pre>
<br />
The name <code>Length</code> is a synonym for <code>int</code> and can be used as follows:
<pre>Length len, maxlen;</pre>
<br />
The <code>typedef</code> keyword can also be used to rename <code>struct</code> data types.
Using the example above:
<pre>typedef struct my_struct_tag MyStructType;
MyStructType mystruct1;
MyStructType mystruct2;</pre>
This creates a new data type name, <code>MyStructType</code> which is synonymous with
the <code>struct my_struct_tag</code> data type, and then defines two variables, <code>
mystruct1</code> and <code>mystruct2</code>.<br /><br />
You could combine the creation of the type name with the creation of the struct data
type:<br />
<pre>typedef struct my_struct_tag
{
int member1;
float member2;
} MyStructType;</pre>
Like the previous example, this creates a new structure data type
and creates a new type name, <code>MyStructType</code> which is synonymous with
<code>struct my_struct_tag</code>. Like the combo example in
the struct section above, the structure tag, <code>my_struct_tag</code> is optional.
However, unlike that example, the identifier following the last curly brace
(<code>MyStructType</code>) is the new type name and not a new variable. To define
the variables, use:<br />
<pre>MyStructType mystruct1;
MyStructType mystruct2;</pre>
See also <a href="http://www.saltycrane.com/blog/2007/02/how-to-share-non-global-c-data/">How to share non-global C data structures</a><br />
<span style="font-family:arial; font-size:65%; color:black;">Technorati tags: <a href="http://technorati.com/tag/c" rel="tag">c</a></span>
Example using bison and flex with cygwin on Windows
2007-02-07T16:52:00-08:00https://www.saltycrane.com/blog/2007/02/example-using-bison-and-flex-with/Here is an example of how to use bison and flex <span class="998365000-08022007">(yacc and lex) </span>with cygwin on windows<span class="998365000-08022007"> xp</span>. <ol> <li>Go to <a href="http://www.cygwin.com/">http://www.cygwin.com/</a>, install Cygwin including bison 2.3-1, flex 2.5.4a-3, gcc-core 3.4.4-1, and make 3.81-1. <br /><br /> </li><li>Create a file called "simple.flex" in "c:\temp": <br />
<pre>%{ <br />#include "simple.tab.h" <br />extern int line_number; <br />%} <br />%option noyywrap <br /> <br />%% <br />"float" { printf("FROM FLEX FLOAT %s\n", yytext); return FLOAT; } <br />"int" { printf("FROM FLEX INT %s\n", yytext); return INT; } <br />[;] { return *yytext; } <br />[_a-zA-Z][_a-zA-Z0-9]* { printf("FROM FLEX IDENTIFIER: %s\n", yytext); return IDENTIFIER; } <br />[ \t\r]+ /* eat up whitespace */ <br />[\n] { line_number++; } <br />%%</pre>
<br /> </li><li>Create a file called "simple.y" in "c:\temp": <br />
<pre>%{ <br /> #include <stdarg.h> <br /> #include "simple_shared.h" <br /> #define YYSTYPE char * <br /> int yydebug=1; <br /> int indent=0; <br /> char *iden_dum; <br />%} <br />%token FLOAT <br />%token INT <br />%token IDENTIFIER <br /> <br />%% /* Grammar rules and actions follow */ <br />declaration: <br /> type_specifier identifier_dum ';' <br /> { printf("%3d: FROM BISON declaration\n", line_number); } <br />; <br />type_specifier: <br /> FLOAT <br /> { printf("%3d: FROM BISON FLOAT\n", line_number); } <br /> | INT <br /> { printf("%3d: FROM BISON INT\n", line_number); } <br />; <br />identifier_dum: <br /> IDENTIFIER <br /> { iden_dum = $1; printf("%3d: IDENTIFIER: %s\n", line_number, &iden_dum); } <br />; <br />%% <br /> <br />main () <br />{ <br /> yyparse (); <br />}</pre>
<br /> </li><li>Create a file called "simple_shared.h" in "c:\temp": <br />
<pre>int line_number=1;</pre>
<br /> </li><li>Create a file called "Makefile" in "c:\temp": <br />
<pre>simple: lex.yy.o simple.tab.o
gcc -o simple $^
simple.tab.h: simple.y
bison --debug --verbose -d simple.y
simple.tab.c: simple.y
bison -d simple.y
lex.yy.c: simple.flex simple.tab.h
flex simple.flex
</pre>
<br /></li><li>Create a file called "input.c" in "c:\temp":
<pre>float variable;</pre>
<br /></li> <li>Open a Cygwin bash shell. <br /> </li><li>"cd /cygdrive/c/temp" <br /> </li><li>"make" <br /> </li><li>"./simple.exe < input.c" </li></ol><br />You should get some output like this: <br />
<pre>$ ./simple.exe < input.c <br />Starting parse <br />Entering state 0 <br />Reading a token: FROM FLEX FLOAT float <br />Next token is token FLOAT () <br />Shifting token FLOAT () <br />Entering state 1 <br />Reducing stack by rule 2 (line 21): <br /> $1 = token FLOAT () <br /> 1: FROM BISON FLOAT <br />-> $$ = nterm type_specifier () <br />Stack now 0 <br />Entering state 4 <br />Reading a token: FROM FLEX IDENTIFIER: variable <br />Next token is token IDENTIFIER () <br />Shifting token IDENTIFIER () <br />Entering state 6 <br />Reducing stack by rule 4 (line 27): <br /> $1 = token IDENTIFIER () <br /> 1: IDENTIFIER: <br />-> $$ = nterm identifier_dum () <br />Stack now 0 4 <br />Entering state 7 <br />Reading a token: Next token is token ';' () <br />Shifting token ';' () <br />Entering state 8 <br />Reducing stack by rule 1 (line 17): <br /> $1 = nterm type_specifier () <br /> $2 = nterm identifier_dum () <br /> $3 = token ';' () <br /> 1: FROM BISON declaration <br />-> $$ = nterm declaration () <br />Stack now 0 <br />Entering state 3 <br />Reading a token: Now at end of input. <br />Stack now 0 3 <br />Cleanup: popping nterm declaration ()</pre>
How to setup the MinGW gcc tools for your Managed Make C Project in CDT 3.1 and Eclipse 3.2
2007-01-24T16:46:00-08:00https://www.saltycrane.com/blog/2007/01/how-to-setup-mingw-gcc-tools-for-your/<div><font face="Arial" color="#000080" size="2"> <div style="FONT-SIZE: small; COLOR: black; FONT-FAMILY: arial"> <div style="FONT-SIZE: small; COLOR: black; FONT-FAMILY: arial"> <div style="FONT-SIZE: small; COLOR: black; FONT-FAMILY: arial"><a href="http://yongshin.blogspot.com/2005/11/how-to-use-cdt-and-mingw-for-eclipse.html">Here</a> is a good article about how to setup MinGW tools with CDT and Eclipse. However I got one error when I setup my project. I got a <pre>"/usr/bin/sh: c:mingwbinmingw32-gcc: command not found"</pre>error. This was because I had "c:\cygwin\bin" in my path. To remedy this, you can set the "PATH" environment variable for your project. This will allow you to search the "c:\mingw\bin" path instead of the "c:\cygwin\bin" path without changing your path outside of Eclipse. This is also the solution if you have the wrong "include" directories listed in your "Includes" folder. E.g., if you have cygwin directories in your "Includes" folder, probably the cygwin gcc command is being used. See also my other post, <a href="http://www.saltycrane.com/blog/2006/10/how-to-set-include-paths-for-gcc-in/">How to set the include paths for gcc in a Managed Make project in Eclipse 3.2.1 and CDT 3.1</a><br /><br />Update 2/5/2007:<br /> You will also likely get a warning which says: <code>Error launching 'cygpath' command'</code><br /> See my post, <a href="http://www.saltycrane.com/blog/2007/02/eclipsecdt-bug-error-launching-cygpath/">Eclipse/CDT bug: Error launching 'cygpath' command</a> about that.<br />To setup a GDB debugger, see my post, <a href="http://www.saltycrane.com/blog/2007/02/how-to-use-mingw-gdb-debugger-with/">How to use the mingw gdb debugger with Eclipse 3.2 / CDT 3.1</a><br />Also, here is another good tutorial about setting up CDT: <a href="http://max.berger.name/howto/cdt/">http://max.berger.name/howto/cdt/</a><br /><br />Here are the detailed steps:<br /> <ol> <li>Right-click on your project and select "Properties"</li> <li>Select "C/C++ Build" from the sidebar</li> <li>Click the "Tool Settings" tab</li> <li>Click the "GCC C Compiler" and enter "mingw32-gcc" in the "Command:" field</li> <li>Click the "GCC C Linker" and enter "mingw32-gcc" in the "Command:" field</li> <li>Click the "Build Settings" tab</li> <li>Uncheck the "Use default command" checkbox</li> <li>Replace "make" with "mingw32-make -k"</li> <li>Click the "Environment" tab; click the "Configuration" tab</li> <li>Click the "New" button</li> <li>From the "Name" dropdown box, select "Path"</li> <li>In the "Value" field, delete the contents and enter "C:\mingw\bin"</li> <li>In the "Delimiter" field, leave it as ";"</li> <li>In the "Operation" field, select "Replace"</li> <li>Click "OK"; click "OK"</li></ol></div></div></div></font></div>
How to use Eclipse and CDT to edit C source files
2007-01-19T15:59:00-08:00https://www.saltycrane.com/blog/2007/01/how-to-use-eclipse-and-cdt-to-edit-c/Eclipse is a good integrated development environment rivaling Microsoft Visual Studio 2005. I have Visual Studio 2005 installed on my computer, though for some reason, I don't care to use it. Eclipse originally was used for Java development but now includes plugins for C/C++, Python, Perl, and many others. I use the Pydev plugin for Python development and it is good.<br /><br />
I am using Tornado 2.2 to develop C code for VxWorks. The editor in Tornado isn't the greatest, so I want to edit my code in Eclipse with the CDT plugin. I will still be using Tornado to build the projects, so instead of using a Standard or Managed Make Project, I just created a folder which linked to my source files. Note that you may get messages in Tornado that say "This file has been changed outside the source editor. Do you want to reload it?" Just make sure you don't have any unsaved changes from Tornado and click "Yes". Or just make sure all your source code windows are closed in Tornado. I know this isn't the most elegant solution, but it will have to do unless we upgrade to VxWorks 6 and Workbench.<br /><br />
Update 2/13/07: I've found a better way to use Eclipse with Tornado projects. See my post <a href="http://www.saltycrane.com/blog/2007/02/how-to-use-tornado-gnu-tools-with/">How to use Tornado GNU tools with Eclipse/CDT</a> for how to use Eclipse to edit *and build* your Tornado project.<br /><br />
Here are the steps:<br />
<ol>
<li>Start with your .c and .h files in a directory called "c:\sofeng\proj\stuff"</li>
<li>Download and install eclipse-SDK-3.2.1-win32.zip from <a href="http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.2.1-200609210945/eclipse-SDK-3.2.1-win32.zip">http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.2.1-200609210945/eclipse-SDK-3.2.1-win32.zip</a></li>
<li>Download and install org.eclipse.cdt-3.1.1-win32.x86.zip from <a href="http://download.eclipse.org/tools/cdt/releases/callisto/dist/3.1.1/">http://download.eclipse.org/tools/cdt/releases/callisto/dist/3.1.1/</a></li>
<li>Run "eclipse.exe"<br />5. From the menu: "Window" -> "Open Perspective" -> "Other..." -> "C/C++" -> "OK"</li>
<li>From the menu: "File" -> "New" -> "Other..."</li>
<li>Under "General", select "Project"</li>
<li>Click "Next"</li>
<li>In the "Project name:" field, type "dummy". Leave the "Use default location" box checked.</li>
<li>Click "Finish"</li>
<li>From the menu: "File" -> "New" -> "Folder"</li>
<li>In the "Enter or select the parent folder:" enter or select the "dummy" project you just created.</li>
<li>Click the ">> Advanced" button</li>
<li>Click the "Link to folder in the file system" checkbox and enter "c:\sofeng\proj\stuff" or "Browse..." to that location.</li>
<li>Click "Finish"</li>
</ol>
NOTE: If you do not see the ">> Advanced" button, follow these steps:<br />
<ol>
<li>From the "Window" menu, select "Preferences..."</li>
<li>Go to "General" > "Workspace" > "Linked Resources" and check "Enable linked resources"</li>
<li>Click "OK"</li>
</ol>