An Updated Cdecl — with Macro Expansion
Tags: c, cpp
Published: 2024-01-05 19:05:06

---
title: An Updated Cdecl — with Macro Expansion
published: true
description: A update on cdecl, including its new macro-expandsion feature.
tags: #c #cpp
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-12-31 13:40 +0000
---

## Introduction

It’s been a [while](https://dev.to/pauljlucas/the-all-new-cdecl-30) since I first started updating [cdecl](https://github.com/paul-j-lucas/cdecl). From my previous article:

> Cdecl (_see-**deh**-kull_) is a program for composing and deciphering C (or C++) type declarations or casts, aka “gibberish.”

In the nearly seven years (!) since that article, I have, in fact, kept hacking on cdecl. In that time, I’ve of course added support for many more C & C++ language features (all the way through [C23](https://en.wikipedia.org/wiki/C23_(C_standard_revision)) and [C++23](https://en.wikipedia.org/wiki/C%2B%2B23)).  Additionally, I’ve added support for:

+ Configuration files.
+ Context- and language-sensitive autocompletion.
+ “Did you mean ...?” suggestions in error messages.
+ “[East const](https://mariusbancila.ro/blog/2018/11/23/join-the-east-const-revolution/).”
+ [Embedded C](http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1021.pdf).
+ [Microsoft calling conventions](https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions).
+ Scoped names.
+ [Unified Parallel C](https://upc.lbl.gov/).

Recently, I was doing some research on [C preprocessor](https://en.wikipedia.org/wiki/C_preprocessor) macros and came across [this answer](https://stackoverflow.com/a/11742317/99089) on how to write a set of macros to allow one to implement functions with default arguments in C (yes, C). Saying the macros are complicated is an understatement.  As I [noted](https://dev.to/pauljlucas/cc-preprocessor-macros-fh5#preprocessor-problems):

> Complicated macros are hard to debug because you only ever see the end result of the expansion. There’s no way to see how expansion progresses step-by-step.

So I got the “itch” to write a program to do just that: given a set of macros, expand them step-by-step as an aid to understanding how they work.

While I _could_ have written an entire new program, I decided to add the feature to cdecl. Although macro expansion doesn’t have anything to do with explaining either C or C++ declarations, cdecl already had code for lexing, parsing, hash tables, printing errors and warnings with source location information (and in color), and lots of other useful code that otherwise would have to have been duplicated.

That aside, adding this feature turned out to be quite the undertaking since it’s effectively implementing full [C preprocessor macro expansion with all its weird rules](https://dev.to/pauljlucas/cc-preprocessor-macros-fh5).

## Expanding Macros

But now that it’s done, you can do things like this:

```
cdecl> #define PASTE_HELPER(A,B)  A ## B
cdecl> #define PASTE(A,B)         PASTE_HELPER(A,B)
cdecl> expand PASTE(var_, __LINE__)
PASTE(var_, __LINE__) => PASTE_HELPER(A,B)
| A => var_
| B => __LINE__
| | __LINE__ => 42
| B => 42
PASTE(var_, 42) => PASTE_HELPER(var_,42)
| PASTE_HELPER(var_, 42) => A ## B
| PASTE_HELPER(var_, 42) => var_ ## 42
| PASTE_HELPER(var_, 42) => var_42
PASTE(var_, 42) => var_42
```

If I do say so myself, that’s pretty nifty.  (The actual output includes color, in particular text that’s substituted is colored differently so you can easily distinguish it.  Yes, the colors are fully customizable.)

## Warnings

As [shown](https://dev.to/pauljlucas/cc-preprocessor-macros-fh5#-raw-endraw-and-raw-endraw-argument-pitfalls), the preprocessor operators of `#` and `##` have a pitfall that often ensnares new users.  A naive implementation of `PASTE` is:

```c
#define PASTE(A,B)  A ## B
```

When you expand it, cdecl will _warn_ you (something a real C preprocessor won’t do):

```
cdecl> expand PASTE(var_, __LINE__)
PASTE(var_, __LINE__) => A ## B
PASTE(var_, __LINE__) => var_ ## __LINE__
                                 ^
34: warning: "##" doesn't expand macro arguments; "__LINE__" will not expand
PASTE(var_, __LINE__) => var___LINE__
```

Pretty nifty, again.

## Conclusion

Cdecl is still a fun project to hack on. If history is any guide, I’ll probably _keep_ hacking on cdecl.