Chris X Edwards

--------------------------

I'm Dreaming Of A White C

2015-09-01 16:37

This summer I’ve been doing something about the fact that I don’t get as much chance to work with C as I would like. One of the problems I’ve had is that I just don’t have enough programming problems that would require the badassery of C. 99% of the time it is much easier for me to dash off a program in Python and be done quickly. Reflecting on why it is that I tend to not use C I realized that Python has a list of features that are so extremely useful that C is hard to justify. Giving this some thought, I realized that I have been missing the point of C. No, C does not come with the features I love about Python, but nor does it come with the "features" I don’t necessarily care for in PHP. What it does come with is a blank slate, the minimum components to express yourself in software (that is portable). And here’s the important part - if something is missing in C that you think is important, you are free to implement it and #include it for the rest of your life. Just the way you like it.

With this new spirit I’ve been merrily attacking problems in C which I normally would expediently solve with Python. I’ve been adding my own strategies for dealing with dynamic memory, strings, data structures, etc. I find C is already extremely good at dealing with Linux calls, file system operations, unvarnished IO, etc. And once into seriously hard stuff (regexp, hard math, etc) C has libraries that are often the last word on the topic.

When I started this agenda, I had hesitated because there was one thing about Python that I loved above all other features in all programming languages I’d ever seen and that was semantic whitespace. I was thinking that it would be a real downer to have to start using all those horribly inscrutable curly braces like sloppy programmers use. I say sloppy programmers because if you are not sloppy, as any Python programmer will tell you, you do not need curly braces to delimit blocks. Basically this horrible syntax element, "{}", rewards you with the license to write sloppy code. No thanks, and no thanks.

I realized that Python is a C program. There is no reason why I couldn’t use C to write a conversion parser that took correctly indented braceless clean code and output compilable C code. This was a great test of C done the Right Way, i.e. my way. Your way may differ. That’s the beauty of C.

Although the details were quite a puzzle, I finally got the core functioning. The main test was to strip down a version of the program to my version of C, convert it with the unstripped version, and then compile that result. Here is what my code looks like for the function that scans a long character array containing the code and printing a valid C program along the way (i.e. this function is an example of input as well as the primary functionality).

The extension for this style is ".cno" as in "C, no braces" or "snow", the white style of C.

int scan_subsection(char *s, int l)
    int n, i, line_end, line_start, in_indent=1, ilevel=0, plevel=0;
    ss *thess= NULL; // A simple stack.
    for (n= 0;n<l;++n)
        if (in_indent)
            if (s[n] != ' ')
                in_indent= 0;
                line_start= n;
            else
                ++ilevel;
        if (s[n] == '\n')
            if (!in_indent)
                line_end= n;
                in_indent= 1;
                if (ilevel > plevel)
                    thess= ss_push(plevel,thess);
                    printf(" \173 \057\057 %d\n",ilevel);
                else if (ilevel < plevel)
                    printf("\n");
                    while (thess && ilevel < plevel)
                        spacesx(ss_val(thess));
                        printf("\175 \057\057 + %d\n",plevel);
                        plevel= ss_val(thess);
                        thess= ss_pop(thess);
                    if (plevel != ilevel)
                        printf("Indentation error at %d!\n",line_start);
                else
                    printf("\n");
                spacesx(ilevel);
                for (i= line_start;i<line_end;++i)
                    printf("%c",s[i]);
                plevel= ilevel;
                ilevel= 0;
    while (thess)
        printf("\n");
        spacesx(ss_val(thess));
        printf("\175 \057\057  %d wrap-up\n",ss_val(thess));
        thess= ss_pop(thess);
    free(thess);
    return -1;

Obviously syntax highlighting doesn’t work (yet). Here is the output, i.e. hopefully normal C.

int scan_subsection(char *s, int l) { // 4
    int n, i, line_end, line_start, in_indent=1, ilevel=0, plevel=0;
    ss *thess= NULL; // A simple stack.
    for (n= 0;n<l;++n) { // 8
        if (in_indent) { // 12
            if (s[n] != ' ') { // 16
                in_indent= 0;
                line_start= n;
            } // + 16
            else { // 16
                ++ilevel;
            } // + 16
        } // + 12
        if (s[n] == '\n') { // 12
            if (!in_indent) { // 16
                line_end= n;
                in_indent= 1;
                if (ilevel > plevel) { // 20
                    thess= ss_push(plevel,thess);
                    printf(" \173 \057\057 %d\n",ilevel);
                } // + 20
                else if (ilevel < plevel) { // 20
                    printf("\n");
                    while (thess && ilevel < plevel) { // 24
                        spacesx(ss_val(thess));
                        printf("\175 \057\057 + %d\n",plevel);
                        plevel= ss_val(thess);
                        thess= ss_pop(thess);
                    } // + 24
                    if (plevel != ilevel) { // 24
                        printf("Indentation error at %d!\n",line_start);
                    } // + 24
                } // + 20
                else { // 20
                    printf("\n");
                } // + 20
                spacesx(ilevel);
                for (i=line_start;i<line_end;++i) { // 20
                    printf("%c",s[i]);
                } // + 20
                plevel= ilevel;
                ilevel= 0;
            } // + 16
        } // + 12
    } // + 8
    while (thess) { // 8
        printf("\n");
        spacesx(ss_val(thess));
        printf("\175 \057\057  %d wrap-up\n",ss_val(thess));
        thess= ss_pop(thess);
    } // + 8
    free(thess);
    return -1;
} // + 4

It turns out that it was pretty hard to get (bootstrap) a program that could repeat the process. I had a version that would convert a cno version to a C program that actually compiled but that executable could not replicate the trick. The problem turned out to be an indentation error in the original C which should never be allowed to happen! That’s a major point of this way of doing things!

You can see that I named the function scan_subsection. This is all very early work and I’ll probably change that name but I point it out because I originally thought to use recursion to do this job. This is also why the function still returns -1 (stop condition) even though that is no longer used. Recursion seemed a reasonable and clever way to use the call stack to store what level was being processed. The problem is that you need so much context from other parts of the code that it became too complex (for me) to do that way. I’m not saying it can’t be done. Cleverer programmers than I could surely do it, but I eventually just implemented my own stack to keep track of indent level and the complexity eased up quite a bit.

This is just a rough prototype at the moment but it serves as a nice proof of concept that C code does not need the suboptimal syntax it was originally planned with. Next I’ll focus on the semi-colons which should be optional in a multi-line program. Also comments need to be nicely handled and there are a few C details that need special treatment such as struct definition. Overall, I am quite pleased with this small bit of progress.

The Linux Unity I Really Wanted

2015-08-26 08:26

Back in March I mentioned that a lot of the big game development engines were relaxing a lot of the licensing fees (becoming free as in "free beer"). That was nice but still not terribly useful for me as an exclusive Linux user. With Android, SteamOS, and other knock-on Linux technologies, bringing games to Linux has very recently become a non-negligible priority in the industry. The problem for me is that until very, very recently, if a game engine had "Linux support" that meant it could create executable games that ran on Linux. That’s wonderful and I’ve supported this with some Steam purchases. (Most gamers don’t take 20 year breaks!) However being able to actually create games in Linux as a development platform using the major engines remained mostly impossible.

I am thrilled to report that this is changing! Today Unity (not to be confused with the painfully stupid desktop environment created for Ubuntu) is announcing that their editor now has a functional Linux build. But this isn’t even the first!

Coincidentally, this past weekend I had just managed to get the editor for the Unreal Game Engine working in Linux. I was able to make and play with a very simple 3d game based on their demos. This is a huge milestone for Linux and for me personally.

With developers free to use a proper OS like Linux for development it’s likely we’ll see a lot more games that actually work well on that platform. And you thought the Glorious PC Gaming Master Race was condescending. Ha! You ain’t seen nothing. This is going to be a lot of fun!

Fool Me N Times, Shame On You

2015-08-21 07:47

In the Linux world there’s been a debate going on for some years about how to move forward. One approach is to stick with well-established principles that have worked well for 45 years and the other approach is to attempt to make the largest number of potential users comfortable today. I would argue that ultimately the former should drive the latter but apparently this does not seem plausible to most developers. A great introduction to the GNU/Linux problems of our time is this article that mentions many of the projects that many of us long time users often find annoying. I think fundamentally this debate is more about what constitutes success rather than how to achieve it.

Where my sensibilities lie is relatively simple compared to the subtle complexities of the projects in question. Simply put, I require that my computer not lie to me. Computers are hard enough without someone’s idea of "easy" distorting the truth.

To demonstrate the kind of thing I’m talking about I’ll give a simple Apple example. If you look at the Finder and enable show paths it will tell you stuff like this.

"Macintosh HD" -> "Users" -> "xed" -> "Documents"

But that turns out to be a bit of a lie. If you open a terminal and do this…

ls -d /Volumes/Macintosh\ HD/Users/$(whoami)

You’ll get something like:

/Volumes/Macintosh HD/Users/xed

So if you thought that "Macintosh HD" was the top of the file system tree, you were wrong despite OS X’s Finder/GUI wanting you to believe this incorrect thing. More annoying to me is that the reality is this…

ls -d /Users/$(whoami)

Produces…

/Users/xed

The 2nd level directory is "Users" and the top level is actually "/" but apparently only us Unix fans like that story. You can see the real structure of "Macintosh HD" with this…

ls -l /Volumes/Macintosh\ HD
lrwxr-xr-x  1 root  admin  1 Aug 20 01:30 /Volumes/Macintosh HD -> /

That "Macintosh HD" thing is a symbolic link to the top directory. This can create topological problems. For example, this is valid…

$ ls -d /Volumes/Macintosh\ HD/Volumes/Macintosh\ HD/Volumes/Macintosh\ HD/Users/xed/

Which produces…

/Volumes/Macintosh HD/Volumes/Macintosh HD/Volumes/Macintosh HD/Users/xed/

This kind of nonsense where a filesystem tree has pointless cycles in it drives me crazy. This first annoyed me (to put it mildly) with Windows 95 introducing its graphical file system browser that had My Computer (still there on Windows) which contained C: which, of course, some how contains My Computer.

Another place that OS interfaces lie is with "trash" or "recycle". I’m starting to realize that normal people do not understand that when they "put something in the trash" they are really just moving it to a directory named "Trash". Yesterday I helped someone who was dragging around a huge directory of photos (hope they weren’t "sensitive"!) that had come from the Trash directory of a USB stick. This had the double damage of wasting space/transfer time and dragging around photos that someone thought should be deleted. Of course this isn’t just an Apple problem.

Even Unix has its lies. The one I find most irritating is one of the reasons that aforementioned Trash directory of photos didn’t get caught (OS X is a Unix). The directory was actually named .Trashes which means, by Unix convention (ls, Bash, et al), the leading dot caused this file to not be shown. I hate this convention and have worked around it with aliases and dotglob, etc. as needed (which is why I found this), but I think it is wrong.

What I love about Unix is that even where it fibs, it is not hard to get the truth. It is always foreseen that some people will want to know what’s really going on. Even OS X is pretty decent to work with becuase despite its kaleidescope of deceptions in the GUI, you can always open a terminal and just get to the reality of an issue. When I look at the new developments in software, I judge them mainly on how often and how severely they lie to me and how hard they make it for me to find the truth.

Very Insideous Security Problems Part 3

2015-08-14 08:08

Today I came across another nasty problem which lies somewhere in between the these topics and is probably more of a realistic security challenge for free (auditable) software users.

Between the ware that is soft and the ware that is hard, lies the ware that is firm. Of course, firmware is not firm in the "not subject to change or revision" sense as with "firm prices". Quite the opposite. Firmware, by design, can be changed relatively easily.

Just thinking about firmware makes hardened computing freedom fighters start to think of homegrown alternatives and, on cue, here’s the libreboot project. Its relative lack of market penetration provides an idea of how serious the problem of proprietary firmware potentially is. But the story just gets worse. The libreboot developers explain that proprietary firmware is not just about the boot loading.

The most glaring issue on modern Intel hardware is the Management Engine. This is a separate processor that exists in all [modern] Intel chip sets… The management engine provides remote access capabilities, independently from the running operating system. It has full access to your RAM, and it has full networking support.

Throw in some IPMI or other straight up "out-of-band control" (i.e. backdoor) and it’s game, set, match. For us (semi-)normal people, we’ll never know if Big Brother is trying to pick our locks, but for some people, there is no doubt. I’m really curious what Edward Snowden is doing about this. Probably using carrier pigeons as defined in RFC 1149 "A Standard for the Transmission of IP Datagrams on Avian Carriers"

The Good Old Keyboard Days

2015-08-03 09:15

I was struggling to correct the devastating mistake of capslock on the latest (and spectacularly awful) Gnome and I realized why I feel so strongly about this.

a2_kb.jpg

It also explains why I can’t type ampersands and parentheses as well as other characters. I have also been known to hesitate typing equals. I wonder how long it would take for me to be comfortable typing on that again?

I don’t go crazy insisting that modern Tab keys be replaced with Esc. That’s a bit of a sanity check which reassures me that putting a Ctrl to the left of the A key is truly the correct thing to do, at least for programmers. And I don’t even use Emacs! NO, I NEVER DO GET NOSTALGIC FOR TYPING IN ALL UPPER CASE.

--------------------------

For older posts and RSS feed see the blog archives.
Chris X Edwards © 1999-2015