LateralT

Posts tagged with "c"

fsmlib: a small and simple library for Finite State Machines

TLDR: get it here

I wrote this to scratch my own itch. Not because I suffer from NIH syndrome, but because I genuinely searched the web for finite small and simple state machine libraries and I couldn't find what I was looking for. They were all either:

  • Overly complex or bloated.
  • Toy libraries with no real use at all.
  • Ad-hoc implementations suited to a very specific application (but advertised as general-purpose.

So I rolled my own. This one is:

  • Small. Only one source file and one header file. Ideal to dump them into your code base and forget about them.
  • Feature-rich. Specially for a small library. I did it with a pragmatic approach, not an academic one, so you can use it to create both Mealy and Moore FSMs or any kind of hybrid monstrosity you can think of.
  • Application agnostic. It doesn't make any assumptions about the target application.
  • POSIX compatible, in all systems that implement timer_* functions and the itimerspec struct (so no MacOS).
Features:
  • Asynchronous (threaded) and synchronous states.
  • Asynchronous (threaded) and synchronous FSMs.
  • Entry and exit actions.
  • Time-triggered and event-triggered transitions.
  • Transition-triggered functions.

I think there might be some things that could be improved, removed or refactored. There are some "TODO" notes sprinkled over the code, but nothing very important. If you can improve it in any way, please do it.

Programming language design mess: C

Today: C.

But wait, I like C. If there’s a programming language I feel comfortable with, it’s C. I know its quirks, its lights, shadows, weaknesses and strengths. Do I really think it’s poorly designed?

Well, at least it’s not C++. I mean, from a point of view it’s beautifully designed in its simplicity. It was designed as a system programming language, slightly higher level than a macro-assembler, easy to implement and to compile, and predictable. The vast majority of today’s computers is still modelled after it or, in another words, it’s a very simple abstract implementation of a von Neumann machine.

It’s not Dennis Ritche’s fault that we decided to program absolutely everything in it because OMG performance is all I want I need to be as close to the metal as possible and I don’t care if my fabulous app crashes every once in a while as long as I got to do the mallocs with my bare hands.

Still, most of the time (that is, when I’m at OS/driver level) I share Linus Torvalds’ opinions on it:

I like interacting with hardware from a software perspective, and I have yet to see a language that comes even close to C in that respect. [...] When I read C I know what the assembly language will look like, and that’s something I care about.

But then, when I accidentally fall into tasks where I have to tackle even the most trivial (from a HLL point of view) high-level mechanisms and structures, jwz pops into my mind:

I think C is a pretty crummy language. I would like to write the same kinds of programs in a better language.

If you know the basics on how a C toolchain works, you’re surely familiar with the fact that in a C program, any uninitialized non-automatic variable is emitted to the .bss section (normally), and that the C runtime bzeroes that whole section before your actual code starts running, so all these variables are effectively initialized to 0 (a susprisingly large number of professional C software engineers are unaware of this, by the way).

Of course, this is a standard behavior and, as such, it’s defined by the standard:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:
  • if it has pointer type, it is initialized to a null pointer;
  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;
  • if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
  • if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

Note how these sentences in the standard are terminated by semicolons. Note also the words in alarming boldface.

Well, thanks for that! So what happens when the first named member is smaller than the total size of the union? And more important, why is there such a quirky exception to the all-zero rule?

At least in x86 Linux the whole .bss section is cleared by the runtime, and that includes ALL the static variables, no matter the type. But that specific explicit behavior popping its head out of the standard makes me a bit uneasy. Not that I have any problem with that personally, since I’m a sane human and, therefore, don’t use unions ever. But I feel like someday the world may crumble under our feet because of things like these and because of lousy programmers not knowing their tools.

Now seriously, can somebody find a counterexample in any architecture/OS/compiler combination? That would be great for my sanity.

Extending C programs with S7 Scheme

Only an experiment/tutorial, really. Normally I doodle a lot of drafts and dabble in a lot of things, checking the initial possibilities and evaluating all the implementation alternatives, and then I leave all my enterprises unfinished. This is just one of them.

Small and embeddable scripting languages owe most of their popularity to the gaming industry, Lua being the most famous of the bunch (I'm not including more full-fledged languages like Perl or Python here). Surely, having most of the dynamic and prone to change features of your game managed by a dynamic and easy to modify language rather than having it all crammed into a monolithic binary is good programming design, and Lua is fast, small and easily embeddable.

Still, something doesn't look quite right when you contemplate all the possibilities. Why isn't Scheme, which is older, better designed, easier to implement and has an almost infinite number of diverse implementations, more widely used for these tasks? Maybe it's because of the aversion most programmers have to prefix notation and S-expressions, maybe because the almost infinite number of diverse implementations is more of a drawback than an advantage, who knows.


keep reading . . .