cdecl(1)
๐ธ cdecl(1) โ General Commands Manual ๐ธ
okay bestie, welcome to the cdecl page, section 1 of the manual, and honestly? this one's a whole journey. buckle up. ๐
โจ NAME โจ
cdecl, c++decl โ compose and decipher C & C++ declarations and casts
no wait, we're not done, because it's also about macros. keep reading. ๐
โจ SYNOPSIS โจ
cdecl [options] [command ...]
c++decl [options] [command ...]
explain [options] gibberish
โจ DESCRIPTION โจ
okay so first, the elders have spoken, and we're putting their words here verbatim because iconic:
``I'm still uncertain about the language declaration syntax, where in declarations, syntax is used that mimics the use of the variables being declared. It is one of the things that draws strong criticism, but it has a certain logic to it.'' โ Dennis M. Ritchie, Creator of C
``I consider the C declarator syntax an experiment that failed.'' โ Bjarne Stroustrup, Creator of C++
fr fr, the inventors themselves said it. ๐
so, cdecl is a program for composing and deciphering C (or C++) declarations or casts โ aka ``gibberish.'' and yes that's the official technical term, we love that for us. ๐ฆ
and that's not all, bestie. cdecl is also for developing and debugging C preprocessor macros by performing expansion step-by-step. main character energy tbh. ๐
cdecl can be used interactively on a terminal or accept input from one of the command-line, standard input, or a file.
โจ INVOCATION โจ
๐ Executable Name ๐
cdecl may be invoked under a number of different names (by either renaming the executable or creating either a symbolic or hard link to it). no cap, the name you call it by changes its whole personality. if it is invoked as:
cdeclโ Runs with the latest supported version of C as the default language.c++decl|cppdecl|cxxdeclโ Runs with the latest supported version of C++ as the default language.explainโ Runs with the latest supported version of C as the default language interpreting the rest of the command-line (if given) as gibberish, performs the conversion to pseudo-English, and exits.
For example (where $ is the shell prompt):
$ explain 'int *const (*p)[4]'
declare p as pointer to array 4 of constant pointer to integer
like??? it just knew. ๐
For declarations given on the command line, care must be taken either to escape or quote shell metacharacters. do not skip this part, the shell WILL eat your asterisks and you will cry. ๐ญ
The default language can be specified via the cdeclrc file (see CONFIGURATION FILES).
๐ First Argument ๐
cdecl will also behave as above if the first non-option argument on the command-line or the first whitespace separated word thereof is a cdecl command (see Commands):
$ cdecl declare p as pointer to array 4 of int
int (*p)[4];
$ c++decl 'reinterpret cast n into pointer to unsigned'
reinterpret_cast<unsigned*>(n)
see how it just... vibes? โจ
๐ Standard Input ๐
If no arguments are given, standard input will be read until end-of-file is encountered or one of the exit, q, or quit commands is read.
You can use cdecl as you create a C (or C++) program from within an editor. For example, in vi(1), type the declaration in pseudo-English, then filter the line through cdecl:
!!cdecl<CR>
where <CR> is the return key. this trick is lowkey life-changing, iykyk. ๐ซถ
๐ Interactive Input ๐
If standard input is coming from a terminal, a prompt of either cdecl> or c++decl> will be written to the terminal before each line of input. The prompt can be turned off by either the --no-prompt or -P option or the set noprompt command.
cdecl uses the GNU readline(3) library (if available and compiled in) to provide keyword completion, command-line history, and editing. so you get tab-completion and history like a civilized person. ๐
โจ OPTIONS โจ
Okay bestie, before we get into the flag buffet, tiny decoder ring: when you see an option argument like f, that means file; n means unsigned integer; and s means string. Slay. ๐
--alt-tokens,-aโ Turns on alternative token output. The alternative tokens are:and(&&),and_eq(&=),bitand(&),bitor(|),compl(~),not(!),not_eq(!=),or(||),or_eq(|=),xor(^), andxor_eq(^=). (Supported only in C95 and later.) โจ--bison-debug,-Bโ Turns onbison(1)debugging output (if compiled in). The additional output is of grammar productions as they are being reduced by the parser. (This is a debugging aid for developers of cdecl itself.) ๐ ๏ธ--color=s,-k sโ Sets when to colorize output tos(which is case-insensitive). (See theCDECL_COLORSenvironment variable about colorization.) The choices forsare:alwaysโ Always colorize.auto | isatty | ttyโ Colorize only when standard output is connected to a TTY (terminal).neverโ Never colorize.not_file | not_isregโ Colorize only when not writing to a regular file (hence writing to a TTY or pipe). (Specifically,fstat(3)is called on standard output: colorize only ifS_IFREGis false.) This is more useful thanisattysince it accommodates the common case of allowing color output to be piped toless(1)and still display in color sincelessunderstands SGR ("Select Graphic Rendition") ASCII terminal escape sequences that produce color.- The default is
not_file.
--commands,-Kโ Prints a sorted list of all cdecl commands for the current language that may be used as the first argument on a command-line. (See First Argument.) This is intended for consumption by a shell completion function. (See also--optionsor-O.) ๐--config=f,-c fโ Specifies the configuration filefto read (see CONFIGURATION FILES).--debug[=s],-d[s]โ Turns on cdecl debugging output:- While parsing a command, prints additional JSON5 output of an abstract syntax tree (AST) as it is being constructed from user input while the parser is reducing grammar productions.
- While expanding a macro, prints additional JSON5 output of the tokens.
- If an error or warning message is printed, includes the
[file:line]of the code that generated said message. - For syntax errors, includes the numeric
[id]of the token that caused the error. (This is a debugging aid for developers of cdecl itself.) Valid formats forsare: uโ Include AST nodeunique_idvalues in JSON5 output as an additional debugging aid. Alternatively,*may be given to mean "all" or-may be given to mean "none."
--digraphs,-2โ Turns on digraph token output. The digraph tokens are:<:([) and:>(]). (Supported only in C95 and later.)--east-const,-eโ Turns on "east const" output whereconst(plus_Atomicandvolatile) are printed to the right ("east") of the type, e.g.:
const int i; // west
int const j; // east
(Not supported in K&R C.)
--echo-commands,-Eโ Echoes commands before their corresponding output, but only when not interactive. (This is primarily useful for associating command output with input in test scripts.)--explicit-ecsu=s,-S sโ For C++ only, sets the type keywords tos(which is case-insensitive) that should be explicitly included in declarations. Valid formats forsare:eโenumcโclasssโstructuโunionMultiple formats may be given, one immediately after the other. Alternatively,*may be given to mean "all" or-may be given to mean "none." The default issu. For example, using the default:
c++decl> declare ps as pointer to struct S
struct S *ps;
c++decl> declare pt as pointer to class T
T *pt;
(See Other Caveats.) For C, enum, struct, and union are always included in declarations.
--explicit-int=s,-i sโ Sets the integer types tos(which is case-insensitive) that should haveintexplicitly included in declarations. (Normally,intis omitted forshort,long,long long, orunsigneddeclarations whereintis implied.) Valid formats forsare:iโ All signed integer types.uโ All unsigned integer types.[u]{i|s|l[l]}โ Possibly unsigned:int,short,long, orlong long. Multiple formats may be given, one immediately after the other, e.g.,uslmeansunsigned shortand (signed)long. Parsing is greedy so commas may be used to separate formats. For example,ulllis parsed asunsigned long longandlongwhereasul,llis parsed asunsigned longandlong long. Note that sinceuis both a shorthand and a modifier,iumeans all signed and unsigned integer types whereasuimeans justunsigned int. Alternatively,*may be given to mean "all" or-may be given to mean "none."
--file=f,-f fโ Reads commands from filef.--flex-debug,-Fโ Turns onflex(1)debugging output (if compiled in). The additional output is of lexer rules as they are being tokenized by the lexer. (This is a debugging aid for developers of cdecl itself.)--help,-hโ Prints a help message for command-line options and exits. ๐--infer-command,-Iโ Tries to infer a command when an input line doesn't start with any. If an input line starts with a:- Macro name, infers
expand; - C (or C++) declaration, infers
explain.
- Macro name, infers
--language=s,-x sโ Specifies which version of what languages(which is case-insensitive) to use. (See C AND C++ LANGUAGE VERSIONS for valid languages.) The default isC23(forcdecl) andC++23(forc++decl).--lineno=n,-L nโ Specifies an integernto add to all line numbers in error and warning messages. (This is a debugging aid for developers of cdecl itself.) This is useful whencdeclis called from a shell script with a here document for input. Consider a test-script (showing line numbers) like:
1 #! /usr/bin/env bash
2 cdecl --echo-commands --lineno=$LINENO <<END
3 explain int
4 END
where $LINENO (the shell environment variable containing the current the line number of the script, in this case, the one cdecl is called on โ in this example: 2) is given. When executed, the script will print:
$ test-script
cdecl> explain int
^
3,12: error: declaration expected
where the line number printed is 3 (the starting line number 1 plus 2 from $LINENO) which is the absolute line number within the script as opposed to the here document that makes locating offending lines easier. (See Other Caveats.)
--no-buffer-stdout,-bโ Sets standard output to unbuffered. (This is a debugging aid for developers of cdecl itself.)--no-config,-Cโ Suppresses reading of any configuration file, even one explicitly specified via either--configor-c.--no-english-types,-Tโ Prints types in C/C++ (e.g.,int), not pseudo-English (e.g.,integer) when explaining gibberish.--no-prompt,-Pโ Suppresses printing of the prompt.--no-semicolon,-sโ Suppresses printing of a final semicolon for C (and C++) declarations.--no-typedefs,-tโ Suppresses predefining all but required standard types, e.g.,size_t,uint8_t, etc. (See PREDEFINED TYPES.) If given twice, suppresses all standard types. (This is a debugging aid for developers of cdecl itself. Certain results will be incorrect.)--no-using,-uโ Always declares types withtypedefrather thanusingin C++11 and later.--options,-Oโ Prints a sorted list of all cdecl options that may be used on a command-line in an easily parsable form. This is intended for consumption by a shell completion function. (See also--commandsor-K.)--output=f,-o fโ Sends all non-error output to filef.--permissive-types,-pโ Permits keywords in language versions other than the current language as types in pseudo-English. By default, a declaration in C like:
declare p as pointer to class
would result in an "unsupported type in C" error even though class could be a valid user-defined type in C. This option permits such declarations. (See Permissive Types.)
--trigraphs,-3โ Turns on trigraph token output. The trigraph tokens are:??(([),??)(]),??'(^),??'=(^=),??!(|),??!=(|=),??!??!(||), and??-(~). (Supported only between C89 and C17 and between C++03 and C++14.)--trailing-return,-rโ Declares functions and operators using the trailing return type syntax in C++11 and later.--version,-vโ Prints the version number and exits. If given twice, additionally prints the set of configure feature & package options and whether GNUreadline(3)(if compiled in) is genuine.--west-decl=s,-w sโ Sets when to print the*for pointer and&and&&for references adjacent to the type ("west") versus adjacent to the name ("east") tos(which is case-insensitive), e.g.:
int *p; // east
int* q; // west
Valid formats for s are:
bโ Block return type.fโ Function (and pointer to function) return type.lโ User-defined literal return type.oโ Operator return type.rโ All return types (same asbflo).sโ Structured binding.tโ Non-return type. Multiple formats may be given, one immediately after the other. Alternatively,*may be given to mean "all" or-may be given to mean "none." The default isr. However, when more than one name is given in the samedeclarecommand for anything other than a structured binding, the*,&, and&&are always printed adjacent to the name ("east"):
cdecl> declare f, g as function returning pointer to char
char *f(), *g();
๐ C AND C++ LANGUAGE VERSIONS ๐
okay bestie so whatever you hand to --language or -x, or whatever you feed the set command, has to be one of these versions. and the good news?? they're all case-insensitive ๐
so go off with your lowercase era.
Cโ the latest supported version of the C language. just, the freshest one we got. โจCK&R|CKNR|CKR|K&R|K&RC|KNR|KNRC|KR|KRC|C78โ the pre-ANSI Kernighan & Ritchie version of C, like, exactly as given in the first edition of The C Programming Language. vintage. iconic. ancient. ๐บC89|C90โ the C89 (first ANSI C) version of C. it adds support forconst,enum,long double,signed,unsigned char,unsigned long,unsigned short,void,volatile, and function prototypes. also adds C preprocessor token concatenation via##and stringification via#. ๐C95โ the C95 version of C. adds support forwchar_t.C99โ the C99 version of C. adds support for_Bool,_Complex,_Imaginary, inline functions,long long,restrict, and static, type-qualified, and variable length array function parameters. plus C preprocessor variadic macros. ๐ฅC11โ the C11 version of C. adds support for_Alignas,_Atomic,char16_t,char32_t,_Noreturn, and_Thread_local.C17|C18โ the C17 version of C. (minor revision, no new features โ literally equivalent to C11. it's giving "same girl, new name" ๐)C23โ the C23 version of C. adds support foralignas,auto(as a deduced type),_BitInt,bool,char8_t,constexpr,[[deprecated]],false, fixed-type enumerations,[[maybe_unused]],[[nodiscard]],nullptr,[[reproducible]],thread_local,true,typeof,typeof_unqual,[[unsequenced]], and the__VA_OPT__preprocessor macro. she's THRIVING ๐C++โ the latest supported version of the C++ language.C++98โ the C++98 version of C++. adds support forclass, constructors, destructors, exception specifications (throw), mutable data members,namespace, new-style casts, overloaded operators, references, pointers to class members, user-defined conversion, and virtual functions. the origin story fr fr ๐ฆC++03โ the C++03 version of C++. (minor revision, no new features. equivalent to C++98.)C++11โ the C++11 version of C++. adds support foralignas,auto(as a deduced type),[[carries_dependency]],char16_t,char32_t,constexpr,defaultanddeletefor member functions,enum class,final, fixed-type enumerations, function trailing return-types, inline namespaces, lambdas,long long, member function ref-qualifiers,noexcept,[[noreturn]],override, rvalue references,thread_local,using(as a typedef synonym), and user-defined literals. this one ATE. ๐ญโจC++14โ the C++14 version of C++. adds support forautoandconstexprreturn types and[[deprecated]].C++17โ the C++17 version of C++. adds support for inline variables,[[maybe_unused]], nested namespace declarations,[[nodiscard]], and structured bindings.C++20โ the C++20 version of C++. adds support forautoparameters and parameter packs,char8_t,consteval,constinit, default relational operators,export, nested inline namespaces,[[no_unique_address]],operator<=>, and the__VA_OPT__preprocessor macro. the spaceship era ๐C++23โ the C++23 version of C++. adds support for_Atomic, explicit object parameters,static operator(), and zero or more parameters foroperator[].C++26โ the C++26 version of C++. adds support for= delete("reason")and[[indeterminate]]. the future is now, bestie ๐ธ
๐ฆ CDECL LANGUAGE ๐ฆ
๐ Commands ๐
real talk, in everything below: [] means zero or one, * means zero or more, {} means one of, and | means alternate. write that down ๐
cdecl has the following commands, babes:
cast [s-name] {as|[in]to} englishโ composes a C (or C++) cast from pseudo-English.{const|dynamic|reinterpret|static} cast s-name {as|[in]to} englishโ composes a C++ new-style cast from pseudo-English.declare s-name [, s-name]* as english [width number [bits]]โ composes C (or C++) declarations from pseudo-English, with an optional bit-field width (integral types only, no cap on that).declare s-name [, s-name]* as english aligned [as|to] { number [bytes] | english }โ composes C (or C++) declarations from pseudo-English, aligned to either a specific number of bytes or to the same alignment as english.declare operator as englishโ C++ only. composes an overloaded operator declaration from pseudo-English.declare store* lambda [[captures] [captures]] [([args])] [returning english]โ C++ only. composes a lambda declaration from pseudo-English. โจdeclare store* user-defined conversion [operator] [of scope-e s-name]* returning englishโ C++ only. composes a user-defined conversion operator from pseudo-English.define s-name as englishโ defines a type (typedef) from pseudo-English.#define name [pp-tokens]โ defines an object-like macro that expands into pp-tokens.#define name([pp-params]) [pp-tokens]โ defines a function-like macro that expands into pp-tokens. heads up bestie: the(must be adjacent toname. no space, no cap. ๐enum [class] s-name [: type]โ defines s-name as an enum (or anenum classin C++) type, optionally of a fixed underlying type. in C, this is equivalent to:
typedef enum s-name s-name
expand name [([pp-args])] [pp-tokens]โ expands a previously defined macro step by step using the supplied arguments (if given). the additional pp-tokens (if given) are appended and expanded.explain gibberish [, gibberish]*โ deciphers C (or C++) declarations, or a new-style cast (C++ only), into pseudo-English.explain (gibberish)[s-name]โ deciphers a C (or C++) cast into pseudo-English.include "path"โ includes the file denoted by path and performs the contained commands. (this is typically used in a configuration file to include another configuration file.) shell meta characters in path, e.g.,~, are expanded.
ngl, note that include is recognized as a cdecl command only when immediately followed by a string literal. adjacent or it didn't happen. ๐
#include "path"โ same asinclude, except#includemay not end with;and must be on a line by itself.{ struct | union | class } s-nameโ defines s-name as a struct, union, or class (C++ only) type. in C, this is equivalent to:
typedef { struct | union } s-name s-name
scope-c s-name { [{ scope-c | typedef | using } ;]* }โ C++ only. defines s-name as a scope-c (struct, union, or class) type; or begins a namespace. also executes zero or more class, struct, typedef, union, or using commands within the scope of s-name, thus declaring type(s) within that scope. nesting era ๐ชset [option [= value] | options | lang]*โ first form: sets a particular option (peep Set Options for the valid ones). second form: prints the current value of all options. third form: sets the current language to lang. and if you give it no argument at all, it's equivalent to the second form. no thoughts, just printing every option.show [ s-name | [all] [predefined | user] [glob]] [[as] {english | typedef | using}]- for s-name, shows the definition for a previously defined type (via
define,typedef, orusing) having that name. - for
allonly, shows all predefined and user-defined types. - for
predefined, shows only predefined types that are valid in the current language or later. - for
user, shows only user-defined types that were defined in the current language or later. - for either
all predefinedorall user, shows their respective set of types regardless of the current language. - for none of s-name,
all,predefined,user, orglob, equivalent toshow user.
- for s-name, shows the definition for a previously defined type (via
by default, types are shown as they were defined. if typedef is given, types are shown as typedef declarations. for C++11 or later only, if using is given, types are shown as using declarations. ๐
show { name | [predefined | user] macros }- for name, shows the definition for a previously defined macro (via
#define) having that name. - for
predefined, shows only predefined macros that are valid in the current language or later. - for
user, shows only user-defined macros. - for neither
predefinednoruser, equivalent toshow user.
- for name, shows the definition for a previously defined macro (via
type[def] gibberish [, gibberish]*โ defines types via a C (or C++) typedef declaration.#undef nameโ undefines a previously defined macro. she's gone, she's undone ๐ซถusing name = gibberishโ for C++11 or later only, defines a type via a using declaration.{ help | ? } [ command[s] | command | english | options ]โ prints help that's sensitive to the current programming language (C or C++). by default, or whencommandorcommandsis given, prints help on cdecl's commands (this very section you're reading, iykyk); ifcommandis given, prints help only for that command; ifenglishis given, prints help on pseudo-English (see English below); ifoptionsis given, prints help on cdecl's options (see Set Options below).exit | q[uit]โ quits cdecl. note thatqis recognized as a synonym forquitonly when it's the only thing on a line other than whitespace. so don't be sneaky about it. ๐
๐ธ where: ๐ธ
- args โ a comma-separated list of s-name, english, s-name as english; or one of
varargs,variadic, or...(ellipsis). - captures โ optionally either copy by default (or
=) or reference by default (or&) followed by a comma-separated list of name or reference to name. - name โ a valid C (or C++) identifier.
- operator โ a valid C++ operator.
- s-name โ for C, is the same as name; for C++, is either the same as name or is a scoped name that may always be specified using
::, e.g.,S::T::x, or in an english context, may alternatively be specified as s-name[of scope-e s-name]*. globโ okay so for C, this is a name; or for C++, it's a scoped name that may contain::. Either may contain*as a wildcard, e.g.,T*(any type name starting withT),*::T*(any type name starting withTin any top-level scope). As a special case for C++,globmay start with**::to match a type name in any scope. slay ๐pp-argsโ a comma-separated list of valid C (or C++) tokens for macro arguments. periodt โจpp-paramsโ a comma-separated list of valid C (or C++) identifiers for macro parameters. In C99 and later, the last parameter may be.... no cap ๐ซถpp-tokensโ a set of valid C (or C++) tokens. iconic ๐ธscope-cโ a C or C++ scope-creating keyword, one of:class,namespace,struct, orunion. fr fr ๐scope-eโ an extended scope-creating keyword, either one ofscope-cor the cdecl-specificscopewhen the particularscope-cis either unknown whenTwasn't previously declared or when it doesn't matter. For example: ๐ฆ
c++decl> explain int T::x
declare x of scope T as integer
cdecl knows T is one of scope-c, but it has no way to know which one so it uses the generic scope. Similarly, you may use scope when you don't care which: the way that ๐ญ
c++decl> declare x of scope T as int
int T::x;
Commands are terminated by either a semicolon or newline. However, commands may be given that span multiple lines when newlines are escaped via \. When a newline is escaped, the next prompt (if enabled) changes to either cdecl+ or c++decl+ to indicate that the current line will be a continuation of the previous line. bestie ๐
Both C-style /* */ comments (even those that span multiple lines) and C++-style // comments within commands are ignored (but see Other Caveats). If /* is entered on a line without its closing */ on the same line, the next prompt (if enabled) changes to either cdecl* or c++decl* to indicate that the current line will be a continuation of the comment until */ is entered. literally ๐
โจ English โจ
In what follows, [] means zero or one, * means zero or more, {} means one of, and | means alternate. The only punctuation characters used in pseudo-English are hyphens in hyphenated words and parentheses around and commas between constructor, function, operator, user-defined literal, or block parameters, and brackets around lambda captures. iykyk ๐
English is one of:
store* ar-qual* array [number|name|*] of english
store* ar-qual* variable [length] array of english
block [([args])] [returning english]
cv-qual* concept s-name [parameter pack]
store* constructor [([args])]
[virtual] destructor [()]
store* fn-qual* [[non-]member] function [([args])] [returning
english]
store* fn-qual* [[non-]member] operator [([args])] [returning
english]
cv-qual* pointer to [member of class s-name] english
[rvalue] reference to english
structured binding
store* user-defined literal [([args])] [returning english]
store* modifier* [C-type]
{ enum [class|struct] [of [type] english] | class | namespace |
struct | union } s-name
where:
ar-qualโ One of:non-empty,const,restrict, orvolatile.C-typeโ One of:auto(C23 or C++11 or later),bool,char,char8_t,char16_t,char32_t,wchar_t,int,float,double,parameter pack, orvoid; or for C99 only:_Accumor_Fract.cv-qualโ One of:_Atomic,const,restrict, orvolatile.fn-qualโ One of:const,final,override,reference,restrict,rvalue reference, orvolatile.modifierโ One of:short,long,signed,unsigned,_Complex,_Imaginary, or_Sat(C99 only).numberโ One of a decimal, octal (if starting with0), hexadecimal (if starting with either0xor0X), or binary (if starting with either0bor0B) number.storeโ One of:auto(C17 or earlier, or C++03 or earlier),block,carries-dependency,consteval,constexpr,deprecated,explicit,export,extern,extern "C",final,friend,inline,maybe-unused,mutable,nodiscard,non-throwing,noreturn,override,register,reproducible,static,thread-local,typedef,unsequenced,virtual, orpure virtual.
If returning english is omitted, it's equivalent to returning int in C95 and earlier or returning void in C99 and later or C++. obsessed ๐
๐ธ Synonyms ๐ธ
Some synonyms are permitted within pseudo-English. The terms on the left are synonyms for what's on the right: ate โจ
accumโ_Accumatomicโ_Atomicautomaticโautobit precise integerโ_BitIntbit-precise integerโ_BitIntboolโ_Boolbooleanโ_BoolBooleanโ_Boolcaptureโcapturingcapturesโcapturingcarries dependencyโcarries_dependencycarries-dependencyโcarries_dependencychar 8โchar8_tchar 16โchar16_tchar 32โchar32_tcharacterโcharcommandโcommandscomplexโ_Complexconstantโconstconstant evaluationโconstevalconstant-evaluationโconstevalconst-evalโconstevalconstant expressionโconstexprconstant-expressionโconstexprconst-exprโconstexprconstant initializationโconstinitconstant-initializationโconstinitconst-initโconstinitconvโconversionctorโconstructordouble precisionโdoubledouble-precisionโdoubledtorโdestructorenumerationโenumevalโevaluationexportedโexportexprโexpressionexternalโexternfloating pointโfloatfloating-pointโfloatfractโ_Fractfuncโfunctionimaginaryโ_Imaginaryinitโinitializationintegerโintlenโlengthmaybe unusedโmaybe_unusedmaybe-unusedโmaybe_unusedmbrโmemberno discardโnodiscardno-discardโnodiscardnon-discardableโnodiscardno exceptโnoexceptno-exceptโnoexceptno-exceptionโnoexceptno unique addressโno_unique_addressno-unique-addressโno_unique_addressnon-unique-addressโno_unique_addressnon-mbrโnon-membernoreturnโ_Noreturnno returnโ_Noreturnno-returnโ_Noreturnnon-returningโ_Noreturnnon-throwingโthrow()operโoperatoroverriddenโoverridepredefโpredefinedptrโpointerrefโreferencerestrictedโrestrictretโreturningsatโ_Satsaturatedโ_Satstructureโstructtypeโtypedefthread localโthread_localthread-localโthread_localthread_localโ_Thread_localuser definedโuser-defineduser-defโuser-definedvarโvariablevarargsโ...variadicโ...vectorโarraywide characterโwchar_t
๐ฆ Gibberish ๐ฆ
Gibberish is any supported C (for cdecl) or C++ (for c++decl) declaration of a variable, constant, array, macro, pointer, reference, rvalue reference, function, constructor, destructor, or overloaded operator; or user-defined type, conversion, or literal; or type cast. (See EXAMPLES for examples and CAVEATS for unsupported declarations.) not me ๐ญ
Gibberish also includes support for the following:
- Apple's ``blocks'' syntax and the
__blockstorage class. - For C99 only, Embedded C's
_Accumand_Fracttypes, and the_Satmodifier. - For C99 only, Unified Parallel C's
relaxed,shared, andstrictqualifiers. - GNU C's
__auto_type,__complex,__complex__,__const,__inline,__inline__,__restrict,__restrict__,__signed,__signed__,__thread,__typeof__,__volatile, and__volatile__. - GNU C's
__attribute__syntax, but all attributes are ignored. - Microsoft C's
__declspecsyntax, but all attributes are ignored. - Microsoft C's calling conventions
__cdecl,__clrcall,__fastcall,__stdcall(alsoWINAPI),__thiscall, and__vectorcall. Pseudo-English also allows the same convention names but without the leading__. - Microsoft C's
__forceinline, but it's treated as a synonym forinline. - Microsoft C's
_asm,_cdecl,_declspec,_fastcall,_forceinline,_inline,_restrict,_stdcall, and_vectorcallthat are synonyms for their respective__counterparts.
๐ Set Options ๐
The set command takes several options (which ignore hyphens). Unambiguous option abbreviations may be used. main character energy ๐
[no]alt-tokensโ Turns [off] on alternative token output โ default is off. (Supported only in C95 and later.)[no]bison-debugโ Turns [off] onbison(1)debugging output (if compiled in) โ default is off.debug[=s]โ Turns on cdecl debugging output โ default is off. (See the--debugor-doption for details.)nodebugโ Turns off cdecl debugging output.nographsโ Turns off either digraph or trigraph output, i.e., reverts to emitting all characters as-is.digraphsโ Turns on digraph output for[and]โ default is off. (Supported only in C95 and later.)[no]east-constโ flips [off] on the "east const" output vibe, whereconst(plus_Atomicandvolatile, the whole crew) gets printed to the right ("east") side of the type instead of the left. Default is off. (Not supported in K&R C, soz โ that era said no.) ๐งญ[no]echo-commandsโ flips [off] on echoing commands before the output they produce, but only when you're not interactive. Default is off. ๐ฃ๏ธ[no]english-typesโ flips [off] on printing types in pseudo-English (likeinteger) instead of C/C++ (likeint) when it's explaining gibberish back at you. Default is on. ๐ฌexplicit-ecsu=sโ C++ only bestie ๐ turns on explicitenum,class,struct, orunionin declarations. Default issu(that'sstructandunion). (See the--explicit-ecsuor-Soption for the details.)explicit-int=sโ turns on explicitintfor the integer types s. Default isnone. (See the--explicit-intor-ioption for the details.)noexplicit-ecsuโ C++ only: turns off explicitenum,class,struct, andunionin declarations. ๐ซnoexplicit-intโ turns off explicitintfor all the integer types. every single one. gone. ๐[no]flex-debugโ flips [off] onflex(1)debugging output (if it was compiled in, iykyk). Default is off. ๐[no]infer-commandโ flips [off] on trying to guess a command when your input line doesn't start with one. Default is off. (See the--infer-commandor-Ioption for the details.) ๐ฎlanguage=sโ use s as the current language (s is case-insensitive, no need to yell). (See C AND C++ LANGUAGE VERSIONS for which languages actually count.) ๐langโ cute lil shorthand forlanguage=lang. ๐optionsโ prints the current value of all the options. like a vibe check for your whole config. โจ[no]permissive-typesโ flips [off] on permitting keywords from language versions other than your current language to be used as types. Default is off. (See the--permissive-typesor-poption for the details.)[no]promptโ flips [off] on the prompt. Default is on. ๐ซ[no]semicolonโ flips [off] on printing a;at the end of a C (or C++) declaration. Default is on. periodt. ๐trigraphsโ turns on trigraph output for[,],^,|, and~. Default is off. (Only supported between C89 and C17, and between C++03 and C++14 โ outside those windows it's a no.) ๐บ[no]trailing-returnโ flips [off] on declaring functions and operators using the trailing return type syntax in C++11 and later. Default is off. โฉ๏ธ[no]usingโ flips [off] on declaring types withusingrather thantypedefin C++11 and later. Default is on. ๐ซถwest-decl=sโ turns on printing the*for pointer and&and&&for reference types adjacent to the type ("west" side) according to s. Default isr(only all return types). (See the--west-declor-woption for the details.) ๐nowest-declโ turns off printing the*for pointer and&and&&for reference types adjacent to the type ("west") for all types. ๐ซ
๐ธ the intro bit (aka the rules of the type buffet) ๐ธ
okay so listen bestie ๐
these types are predefined โ like, they come free with your cdecl, no work required โ unless you pass either the --no-typedefs or -t option. and they show up in the specified language and later, so pick your era and you get that era's whole wardrobe plus everything before it. slay.
โ ๏ธ but wait, there's a plot twist for the C++ girlies:std::partial_ordering,std::strong_ordering, andstd::weak_orderingare always defined in C++20 and later, becauseoperator<=>()literally cannot function without them โ unless the option is given twice. yes, twice. the double-tap undoes it. iykyk. ๐ญ
๐ K&R C
the vintage. the og. the thrift-store find that's actually worth a fortune.
caddr_t, daddr_t, dev_t, FILE, ino_t, jmp_buf, off_t, time_t, tm
๐ C89
so many types, so little time. this is the big one, buckle up ๐ฆ
blkcnt_t, blksize_t, cc_t, clockid_t, clock_t, DIR, div_t, double_t,
errno_t, fd_set, femode_t, fenv_t, fexcept_t, float_t, fpos_t,
fsblkcnt_t, fsfilcnt_t, gid_t, iconv_t, id_t, imaxdiv_t, in_addr_t,
in_port_t, key_t, ldiv_t, lldiv_t, locale_t, long_double_t, mbstate_t,
mode_t, nfds_t, nlink_t, pid_t, posix_spawnattr_t,
posix_spawn_file_actions_t, ptrdiff_t, regex_t, regmatch_t, regoff_t,
rlim_t, sa_family_t, sig_atomic_t, sighandler_t, sigset_t, sig_t,
size_t, socklen_t, ssize_t, suseconds_t, timer_r, uid_t, useconds_t,
va_list,
and then the decimal squad shows up ๐
_Decimal32, _Decimal32_t, _Decimal64, _Decimal64_t, _Decimal64x,
_Decimal128, _Decimal128_t, _Decimal128x,
and then the float squad โจ
_Float16, _Float16_t, _Float32, _Float32_t, _Float32x, _Float64,
_Float64_t, _Float64x, _Float128, _Float128_t, _Float128x
๐ C95
pthreads girlies rise ๐ this one comes in three courses:
course one โ the pthread lineup:
pthread_t, pthread_barrier_t, pthread_barrierattr_t, pthread_cond_t,
pthread_condattr_t, pthread_key_t, pthread_mutex_t, pthread_mutexattr_t,
pthread_once_t, pthread_rwlock_t, pthread_rwlockattr_t,
pthread_spinlock_t, wctrans_t, wctype_t, wint_t,
course two โ the compiler-intrinsics-y ones:
__float80, __float128, __fp16, __ibm128, __int128, __m128, __m128d,
__m128i, __m64,
course three โ and then THE WINDOWS WALL. yes. all of it. i'm not skipping a single one, that's not the vibe, we don't do that here ๐
ATOM, BOOL, BOOLEAN, BYTE, CCHAR, CHAR, COLORREF, DWORD, DWORD32,
DWORD64, DWORDLONG, DWORD_PTR, FLOAT, HALF_PTR, HANDLE, HBITMAP, HBRUSH,
HCOLORSPACE, HCONV, HCONVLIST, HCURSOR, HDC, HDDEDATA, HDESK, HDROP,
HDWP, HENHMETAFILE, HFILE, HFONT, HGDIOBJ, HGLOBAL, HHOOK, HICON,
HINSTANCE, HKEY, HKL, HLOCAL, HMENU, HMETAFILE, HMODULE, HMONITOR,
HPALETTE, HPEN, HRESULT, HRGN, HRSRC, HSZ, HWINSTA, HWND, INT, _int8,
_int16, _int32, _int64, __int8, __int16, __int32, __int64, INT_PTR,
LANGID, LARGE_INTEGER, LCID, LCTYPE, LGRPID, LONG, LONG32, LONG64,
LONGLONG, LONG_PTR, LPBOOL, LPBYTE, LPCHAR, LPCOLORREF, LPCSTR, LPCTSTR,
LPCVOID, LPCWSTR, LPDWORD, LPHANDLE, LPINT, LPLONG, LPSTR, LPTSTR,
LPVOID, LPWORD, LPWSTR, LRESULT, PBOOL, PBOOLEAN, PBYTE, PCHAR, PCSTR,
PCTSTR, PCWSTR, PDWORD, PDWORD32, PDWORD64, PDWORDLONG, PDWORD_PTR,
PFLOAT, PHALF_PTR, PHANDLE, PHKEY, PINT, PINT16, PINT32, PINT64, PINT8,
PINT_PTR, PLCID, PLONG, PLONG32, PLONG64, PLONGLONG, PLONG_PTR, PSHORT,
PSIZE_T, PSSIZE_T, PSTR, PTBYTE, PTCHAR, PTSTR, PUCHAR, PUHALF_PTR,
PUINT, PUINT16, PUINT32, PUINT64, PUINT8, PUINT_PTR, PULONG, PULONG32,
PULONG64, PULONGLONG, PULONG_PTR, PUSHORT, PVOID, PWCHAR, PWORD, PWSTR,
QWORD, SC_HANDLE, SC_LOCK, SERVICE_STATUS_HANDLE, SHORT, SIZE_T,
SSIZE_T, TBYTE, TCHAR, UCHAR, UHALF_PTR, UINT, UINT16, UINT32, UINT64,
UINT8, UINT_PTR, ULARGE_INTEGER, ULONG, ULONG32, ULONG64, ULONGLONG,
ULONG_PTR, UNICODE_STRING, USHORT, USN, WCHAR, __wchar_t, WORD, WPARAM
ate. no crumbs. ๐
๐ง C99
the fixed-width era, we love her ๐
int8_t, int16_t, int32_t, int64_t, intmax_t, intptr_t, uint8_t,
uint16_t, uint32_t, uint64_t, uintmax_t, uintptr_t,
then the fast-and-least gang ๐โโ๏ธ
int_fast8_t, int_fast16_t, int_fast32_t, int_fast64_t, int_least8_t,
int_least16_t, int_least32_t, int_least64_t, uint_fast8_t,
uint_fast16_t, uint_fast32_t, uint_fast64_t, uint_least8_t,
uint_least16_t, uint_least32_t, uint_least64_t,
and these little cryptic cuties ๐ธ
int_hk_t, int_hr_t, int_k_t, int_lk_t, int_lr_t, int_r_t, uint_uhk_t,
uint_uhr_t, uint_uk_t, uint_ulk_t, uint_ulr_t, uint_ur_t
โญ C11
atomics!!! the main character energy of concurrency ๐ซถ
atomic_bool, atomic_char16_t, atomic_char32_t, atomic_char, atomic_flag,
atomic_int, atomic_intmax_t, atomic_intptr_t, atomic_llong, atomic_long,
atomic_ptrdiff_t, atomic_schar, atomic_short, atomic_size_t,
atomic_uchar, atomic_uint, atomic_uintmax_t, atomic_uintptr_t,
atomic_ullong, atomic_ulong, atomic_ushort, atomic_wchar_t,
the fast/least atomic remix:
atomic_int_fast8_t, atomic_int_fast16_t, atomic_int_fast32_t,
atomic_int_fast64_t, atomic_int_least8_t, atomic_int_least16_t,
atomic_int_least32_t, atomic_int_least64_t, atomic_uint_fast8_t,
atomic_uint_fast16_t, atomic_uint_fast32_t, atomic_uint_fast64_t,
atomic_uint_least8_t, atomic_uint_least16_t, atomic_uint_least32_t,
atomic_uint_least64_t,
and the threads support cast:
cnd_t, constraint_handler_t, max_align_t, memory_order, mtx_t,
once_flag, rsize_t, thrd_start_t, thrd_t, tss_dtor_t, tss_t
๐ฆ C23
just one. a single icon. the moment. ๐
nullptr_t
๐ C++98
std-namespace besties, assemble โจ
std::bad_alloc, std::bad_cast, std::bad_exception, std::bad_type_id,
std::codecvt_base, std::ctype_base, std::ctype_base::mask, std::div_t,
std::domain_error, std::exception, std::filebuf, std::fstream,
std::ifstream, std::invalid_argument, std::ios, std::ios_base::Init,
std::ios_base::event, std::ios_base::event_callback,
std::ios_base::fmtflags, std::ios_base::iostate,
std::ios_base::openmode, std::ios_base::seekdir, std::ios_base,
std::iostream, std::istream, std::istringstream, std::lconv,
std::ldiv_t, std::length_error, std::locale, std::logic_error,
std::messages_base, std::money_base, std::new_handler, std::nothrow_t,
std::ofstream, std::ostream, std::ostringstream, std::osyncstream,
std::out_of_range, std::overflow_error, std::ptrdiff_t,
std::range_error, std::runtime_error, std::sig_atomic_t, std::size_t,
std::streambuf, std::streamoff, std::streamsize, std::string,
std::stringbuf, std::stringstream, std::syncbuf, std::time_base,
std::tm, std::underflow_error, std::wfilebuf, std::wfstream,
std::wifstream, std::wios, std::wiostream, std::wistream,
std::wistringstream, std::wofstream, std::wostream, std::wostringstream,
std::wosyncstream, std::wstreambuf, std::wstring, std::wstringbuf,
std::wstringstream, std::wsyncbuf
๐ฅ C++11
okay this one is huge and i am obsessed ๐ญ first up, the atomic section โ yes there are two char8_t-adjacent surprises in here, look:
std::atomic_bool, std::atomic_char16_t, std::atomic_char32_t,
std::atomic_char8_t, std::atomic_char, std::atomic_flag,
std::atomic_int16_t, std::atomic_int32_t, std::atomic_int64_t,
std::atomic_int8_t, std::atomic_int_fast16_t, std::atomic_int_fast32_t,
std::atomic_int_fast64_t, std::atomic_int_fast8_t, std::atomic_int,
std::atomic_int_least16_t, std::atomic_int_least32_t,
std::atomic_int_least64_t, std::atomic_int_least8_t,
std::atomic_intmax_t, std::atomic_intptr_t, std::atomic_llong,
std::atomic_long, std::atomic_ptrdiff_t, std::atomic_schar,
std::atomic_short, std::atomic_signed_lock_free, std::atomic_size_t,
std::atomic_uchar, std::atomic_uint16_t, std::atomic_uint32_t,
std::atomic_uint64_t, std::atomic_uint8_t, std::atomic_uint_fast16_t,
std::atomic_uint_fast32_t, std::atomic_uint_fast64_t,
std::atomic_uint_fast8_t, std::atomic_uint, std::atomic_uint_least16_t,
std::atomic_uint_least32_t, std::atomic_uint_least64_t,
std::atomic_uint_least8_t, std::atomic_uintmax_t, std::atomic_uintptr_t,
std::atomic_ullong, std::atomic_ulong, std::atomic_unsigned_lock_free,
std::atomic_ushort, std::atomic_wchar_t,
and then the everything-else section (threads, regex, futures, clocks, the whole vibe) ๐
std::adopt_lock_t, std::allocator_arg_t, std::bad_array_new_length,
std::bad_function_call, std::bad_weak_ptr, std::bernoulli_distribution,
std::chrono::high_resolution_clock, std::chrono::steady_clock,
std::condition_variable, std::condition_variable_any, std::cv_status,
std::defer_lock_t, std::error_category, std::error_code,
std::error_condition, std::future_errc, std::future_error,
std::future_status, std::imaxdiv_t, std::ios_base::failure, std::launch,
std::lldiv_t, std::max_align_t, std::mutex, std::nullptr_t,
std::random_device, std::recursive_mutex, std::recursive_timed_mutex,
std::regex, std::regex_constants::error_type,
std::regex_constants::match_flag_type,
std::regex_constants::syntax_option_type, std::regex_error,
std::shared_mutex, std::shared_timed_mutex, std::system_error,
std::thread, std::timed_mutex, std::try_to_lock_t, std::u32string,
std::u32string_view, std::wregex
๐ C++17
string_views, any, variant-adjacent, byte... so modern, so chic ๐ฆ
std::align_val_t, std::any, std::bad_any_cast, std::bad_optional_access,
std::bad_variant_access, std::byte, std::chars_format,
std::from_chars_result, std::memory_resource, std::mono_state,
std::string_view, std::to_chars_result, std::u16string,
std::u16string_view, std::wstring_view,
then the filesystem era arrives (we love a directory iterator):
std::filesystem::copy_options, std::filesystem::directory_entry,
std::filesystem::directory_iterator, std::filesystem::directory_options,
std::filesystem::file_status, std::filesystem::file_type,
std::filesystem::filesystem_error, std::filesystem::path,
std::filesystem::perm_options, std::filesystem::perms,
std::filesystem::recursive_directory_iterator,
std::filesystem::space_info,
and the pmr gang (note: these are listed space-separated, that's how they come, don't @ me):
std::pmr::memory_resource std::pmr::monotonic_buffer_resource
std::pmr::pool_options std::pmr::synchronized_pool_resource
std::pmr::unsynchronized_pool_resource
๐ C++20
coroutines, spaceship operators, chrono going absolutely feral with calendars, stop tokens โ this era ATE ๐ฅ
std::ambiguous_local_time, std::compare_three_way, std::endian,
std::latch, std::noop_coroutine_promise, std::strong_equality,
std::strong_ordering, std::suspend_always, std::suspend_never,
std::nonstopstate_t, std::weak_equality, std::stop_source,
std::stop_token, std::destroying_delete_t, std::format_error,
std::jthread, std::partial_ordering, std::u8string_view,
std::weak_ordering,
and the chrono calendar situation, which is a whole mood ๐๏ธโจ
std::chrono::choose, std::chrono::day, std::chrono::file_clock,
std::chrono::gps_clock, std::chrono::is_clock, std::chrono::last_spec,
std::chrono::leap_second, std::chrono::local_info, std::chrono::local_t,
std::chrono::month, std::chrono::month_day, std::chrono::month_day_last,
std::chrono::month_weekday, std::chrono::month_weekday_last,
std::chrono::nonexistent_local_time, std::chrono::sys_info,
std::chrono::system_clock, std::chrono::tai_clock,
std::chrono::time_zone, std::chrono::time_zone_link, std::chrono::tzdb,
std::chrono::tzdb_list, std::chrono::utc_clock, std::chrono::weekday,
std::chrono::weekday_indexed, std::chrono::weekday_last,
std::chrono::year, std::chrono::year_month, std::chrono::year_month_day,
std::chrono::year_month_day_last, std::chrono::year_month_weekday,
std::chrono::year_month_weekday_last
๐ซถ C++23
floats galore, spanstreams, stacktrace, and an unexpect_t because sometimes things are unexpected, fr fr ๐ญ
std::bfloat16_t, std::float128_t, std::float16_t, std::float32_t,
std::float64_t, std::ispanstream, std::ospanstream, std::range_format,
std::spanbuf, std::spanstream, std::stacktrace, std::stacktrace_entry,
std::unexpect_t, std::wispanstream std::wospanstream, std::wspanbuf,
std::wspanstream
๐ C++26
the future. the final boss. the group chat of types ๐ง
std::hazard_pointer, std::hive_limits, std::rcu_domain, std::text_encoding,
then contracts, which is giving serious "we have rules now" energy ๐
std::contracts::assertion_kind, std::contracts::contract_violation,
std::contracts::detection_mode, std::contracts::evaluation_semantic,
and finally the linear algebra crowd, triangle variants included ๐
std::linalg::column_major_t, std::linalg::explicit_diagonal_t,
std::linalg::implicit_unit_diagonal_t, std::linalg::lower_triangle_t,
std::linalg::row_major_t, std::linalg::upper_triangle_t
โจ PREDEFINED MACROS โจ
okay so these are the macros that just come with the language โ no setup needed, they're already there ๐ and they're predefined in the specified language and later versions too. so if your language is C89, you get the C89 ones, bestie. simple as that.
๐ฉท C89
__DATE__โ the local date, formatted like"Mmm dd yyyy". yes it's giving very specific format, don't fight it.__FILE__โ the name of the file you're currently in, if there is one โ otherwise it's"stdin".__LINE__โ the line number you're currently on within__FILE__, if any โ or like, some arbitrary line number, whatever.__STDC__โ literally just1. (not defined in C++, bestie, don't @ me.)__STDC_VERSION__โ the current C version, e.g.202311Lfor C23. (not defined in C++ either!)__TIME__โ the local time, formatted like"hh:mm:ss". clock it โฐ
๐ธ C99
__VA_ARGS__โ the variable arguments of a macro, if there are any. the icon of variadic macros, fr fr.
๐ฆ C++
__cplusplusโ the current C++ version, e.g.202302Lfor C++23. (not defined in C, so don't go looking for it there ๐)
๐ C23 | C++20
__VA_OPT__โ optional preprocessor tokens, and they're enclosed between parentheses. very "if you know you know" energy.
๐ NOTES ๐
๐ main()
so in C, a function named main gets its parameters and return type checked against what main actually requires. cute, right? but in C++, that check only happens if main is not declared const, consteval, constexpr, default, delete, final, inline, override, __restrict, static, virtual, nor volatile. and if it is declared like that? then it's assumed to be a member function. that's just how it is, periodt.
๐ Permissive Types
okay so permissive types โ that's the thing you turn on with the --permissive-types or -p option โ and the reason it's not the default is lowkey important: always permitting keywords from other language versions as type names can give you genuinely confusing errors. ๐ญ
like, imagine permissive types were the default. then in C, you'd get this:
cdecl> declare D as virtual destructor
^
14: warning: "virtual" is a keyword in C++
virtual D;
^
22: syntax error: "destructor": unexpected token ...
so what happened here? virtual isn't a keyword in C, so it's a perfectly valid name for a user-defined type. so cdecl takes it as a type name, and interprets your request as "declare D as a variable of type virtual" โ and it does it, printing virtual D (while still warning you that virtual is a keyword in C++). but then destructor shows up out of nowhere and boom, error. ๐ and honestly? it could easily be that you just forgot to set the current language to C++ instead of C. we've all been there.
with the default non-permissive behaviour, you get this instead:
cdecl> declare D as virtual destructor
^
14: error: "virtual": unsupported keyword in C
which is so much clearer โ the trade-off being that it won't permit valid declarations that use keywords from other language versions as types. you win some, you lose some ๐ซถ
๐ CONFIGURATION FILES ๐
a configuration file lets you configure cdecl by running the commands inside it on start-up โ unless you pass either the --no-config or -C option, in which case, nope, skipped.
the file's full path comes from the first of these that exists and is readable:
- The value of either the
--configor-coption. - The value of the
CDECLRCenvironment variable. - The first of these files:
~/.cdeclrc
$XDG_CONFIG_HOME/cdecl
~/.config/cdecl
- If the
XDG_CONFIG_DIRSenvironment variable is set to a colon separated list of paths, then for each path in it, the first ofpath/cdecl. /etc/xdg/cdecl
and the commands that are actually useful inside a config file:
class|define|enum|namespace|struct|typedef|union|usingโ pre-define your own user-specific types so you can use them later when you're either composing or deciphering declarations. iconic behaviour honestly.#defineโ pre-define macros so they can be expanded later.include|#includeโ pull in other configuration files. nesting, we love to see it.setโ set the language or other options initially.
config files can have blank lines, C-style/* */comments, and C++-style//comments โ and all of them just get ignored. โจ
๐ EXAMPLES ๐
โญ C Declarations
want an array of pointers to functions that are like malloc(3)? say less:
cdecl> declare fptab as array of pointer to function \
cdecl+ returning pointer to void
void *(*fptab[])();
and when you stumble across that declaration in someone else's code and your brain short-circuits, you make sense of it like this:
cdecl> explain void *(*fptab[])()
the function prototype for something like _exit(2) gets declared with:
cdecl> declare _exit as function (retval as int) returning void
void _exit(int retval);
and for a more complex one, signal(2) would be fully defined as:
cdecl> declare signal as function \
cdecl+ (sig as int, \
cdecl+ f as pointer to function (int) returning void) \
cdecl+ returning pointer to function (int) returning void
void (*signal(int sig, void (*f)(int)))(int);
and that gets so much more comprehensible if you use one of define, typedef, or using:
cdecl> define pfi_v as pointer to function (int) returning void
cdecl> declare signal as function \
cdecl+ (sig as int, f as pfi_v) returning pfi_v
pfi_v signal(int sig, pfi_v f);
cdecl can also help you figure out where to put your const and volatile qualifiers โ because honestly, who can keep that straight:
cdecl> declare pci as pointer to const int
const int *pci;
cdecl> declare cpi as const pointer to int
int *const cpi;
๐ฆ C++ Declarations
c++decl is here to help you declare references, bestie:
c++decl> declare rpc as reference to pointer to char
char *&rpc;
it also handles pointers to members of classes:
c++decl> declare p as pointer to member of class C int
int C::*p;
and:
c++decl> declare p as pointer to member of class C \
c++decl+ function (i as int, j as int) \
c++decl+ returning pointer to class D
D *(C::*p)(int i, int j)
and if you wanna define types within scopes? it's giving very flexible:
c++decl> define A::B::T1 as int
c++decl> define T2 of scope A as int
c++decl> define T3 of scope B of scope A as int
c++decl> define T4 of scope A::B as int
c++decl> define T5 of class C::D as int
c++decl> class C { typedef int T; }
c++decl> class C1 { class C2 { typedef int T; }; }
c++decl> struct S { typedef int T; }
c++decl> namespace N { typedef int T; }
c++decl> namespace N::M { typedef int T; }
c++decl> union U { typedef int T; }
๐ง Preprocessor Macros
cdecl can help you understand how macros expand, and honestly this is the part that eats:
cdecl> #define NAME2_HELPER(A,B) A ## B
cdecl> #define NAME2(A,B) NAME2_HELPER(A,B)
cdecl> expand NAME2(var_, __LINE__)
NAME2(var_, __LINE__) => NAME2_HELPER(A,B)
| A => var_
| B => __LINE__
| | __LINE__ => 42
| B => 42
NAME2(var_, 42) => NAME2_HELPER(var_,42)
| NAME2_HELPER(var_, 42) => A ## B
| NAME2_HELPER(var_, 42) => var_ ## 42
| NAME2_HELPER(var_, 42) => var_42
NAME2(var_, 42) => var_42
๐ช EXIT STATUS ๐ช
0โ Success. we love to see it ๐64โ Command-line usage error. you typed something weird, no judgement.65โ Syntax or semantic error.66โ Open file error.70โ Internal software error. (Please report the bug. seriously, tell someone ๐)71โ System error.73โ Create file error.74โ I/O error.
ENVIRONMENT ๐
CDECL_COLORSโ bestie this one sets the colors and all the other attributes used to highlight the different bits of the output, and it works the same way asGCC_COLORSdoes forgcc.
Just like with gcc, the value is a colon-separated sequence of capabilities. Each capability looks like name[=SGR] where name is a capability name and SGR, if it's there at all, is a "Select Graphic Rendition" value โ that's a semicolon-separated list of integers in the range 0-255. An example SGR value is 31;1, which gives you a bright red foreground over the terminal's default background. โจ
Capability names with upper-case letters in them are unique to cdecl; the all-lower-case ones are upwards compatible with gcc. iykyk ๐
caret=SGRโ the SGR for the caret pointing to the error on the line above (same asgcc). Default is32;1(bright green foreground over current terminal background).error=SGRโ the SGR for the word ``error.'' Default is31;1(bright red foreground over current terminal background).HELP-keyword=SGRโ the SGR for keywords in help output. Default is1(bold terminal foreground over current terminal background).HELP-nonterm=SGRโ the SGR for nonterminals in help output. Default is36(cyan foreground over current terminal background).HELP-punct=SGRโ the SGR for punctuation in help output. Default is30;1(dark gray foreground over current terminal background).HELP-title=SGRโ the SGR for titles in help output. Default is34;1(bright blue foreground over current terminal background).locus=SGRโ the SGR for location information in error and warning messages. Default is1(bold current foreground over current terminal background).MACRO-no-expand=SGRโ the SGR for a macro that can not expand. Default is35(magenta foreground over current terminal background).MACRO-punct=SGRโ the SGR for macro expansion punctuation. Default is32;1(bright green foreground over current terminal background).MACRO-subst=SGRโ the SGR for macro substituted tokens. Default is36(cyan foreground over current terminal background).PROMPT=SGRโ the SGR for the prompt. Default is32(green foreground over current terminal background).warning=SGRโ the SGR for the word ``warning.'' Default is33;1(bright yellow foreground over current terminal background).
And ngl, the term "color" is being used loosely here โ besides colors, other character attributes like bold, underlined, reverse video, etc., may also be possible depending on what your terminal can actually do. ๐
CDECL_DEBUGโ if you set this to an "affirmative" value (one of1,t,true,y, oryes, case-insensitive), thencdeclprints its process ID and a ``waiting for debugger to attach'' message to standard error and then waits indefinitely for a debugger to attach. ๐ญ (This is a debugging aid for the developers ofcdeclitself, not a you thing.) It's only enabled whencdeclwas compiled withNDEBUGnot defined.CDECL_TESTโ this one helps with testing when you set it to a non-empty value made of one or more of these letters (and they are case-sensitive, so watch it bestie):cโ don't read any configuration file by default. Either the--configor-coption must be used explicitly.Cโ ignore the actual terminal columns and theCOLUMNSenvironment variable; always use80.hโ don't read any file under the user's home directory by default. Either the--configor-coption must be used explicitly.mโ return constant values for the__DATE__,__FILE__,__LINE__, and__TIME__macros.
You can give multiple letters, one immediately after the other. Or, alternatively, * can be given to mean "all", or - can be given to mean "none."
CDECLRCโ the full path to a configuration file (peep CONFIGURATION FILES). Only used if it's not empty and none of the--config,-c,--no-config, or-Coptions are given.COLUMNSโ the number of columns of the terminal on whichcdeclis being run. Used to get the terminal's width for limiting how long error and warning messages can be. Takes precedence over the number of columns specified by theTERMvariable.HOMEโ used to locate a default configuration file under the user's home directory. If it's unset, the home directory comes from the password database entry for the effective user. If that fails, no default configuration file under the user's home directory gets read. ๐TERMโ the type of the terminal on whichcdeclis being run.XDG_CONFIG_DIRSโ if set to a colon separated list of paths, then for each path in it, the first ofpath/cdeclto exist and be readable is used as the configuration file (peep CONFIGURATION FILES).XDG_CONFIG_HOMEโ if set to a path of a directory and$XDG_CONFIG_HOME/cdeclexists and is readable, then that is used as the configuration file (peep CONFIGURATION FILES).
๐ธ FILES ๐ธ
~/.cdeclrc$XDG_CONFIG_HOME/cdecl~/.config/cdecl/etc/xdg/cdecl
The default configuration file (peep CONFIGURATION FILES).
~/.editrcโ individualeditline(3)initialization file. On systems where thereadline(3)API is provided but is just a wrapper aroundlibedit(e.g., macOS), the~/.editrcfile, if present, is read instead of~/.inputrc. If it's present, add the following (undocumented) command:
bind ^I rl_complete
to make tab-completion work in cdecl. ๐ซถ
~/.inputrcโ individualreadline(3)initialization file.
๐ BUGS ๐
Readline Wrapper Around Editline
On systems where the readline(3) API is provided but is just a wrapper around the Editline Library (e.g., macOS), there are a few issues, and we're gonna spill them all:
- The wrapper has a bug that prevents color prompts from working correctly. So because of that, the
PROMPTcolor capability is ignored on systems that don't provide genuine GNUreadline(3). ๐ - Hitting tab when there are no completion matches ordinarily rings the terminal's bell. But older versions of the wrapper don't provide the
rl_ding()function that's needed to ring the bell, socdeclprovides a substitute. However, the substitute doesn't respect the user's preferred bell style (none, audible, or visual) and always does an audible bell. ๐ญ - In some cases, hitting tab causes the wrapper to suggest only a single completion rather than simply inserting it.
To avoid these issues, compile cdecl against the genuine GNU Readline Library. periodt.
See Also
https://github.com/paul-j-lucas/cdecl/issues
๐ซฃ CAVEATS ๐ซฃ
No cap, bestie, this is the "here's what it can't do yet" part. Read it, love it, don't get caught out by it. ๐
๐ Unsupported Declarations
The following types of declarations are not currently supported:
- Only
enum,class,struct, andunionnames and scoped type declarations are supported; complete declarations are not:
struct S s; // supported
struct S { typedef int Int; }; // supported (C++ only)
struct S { int i; char c; } s; // not supported
- For array sizes, only integer literals, names, and
*are supported; arbitrary expressions are not. - In C23 and later,
autoas a storage-class specifier is no longer supported. - For C23
typeofandtypeof_unqualdeclarations, only types are supported; arbitrary expressions are not:
typeof(int*) x // supported
typeof(x) y // not supported
- Only C++ lambda signature declarations are supported; complete lambda declarations are not:
[n](int x) // supported
[n](int x) { return n * x; } // not supported
- C++
decltype, abbreviated function template, default argument, and template declarations are not supported. ๐ญ - For C++ function exception specifications, only
noexcept,noexcept(true),noexcept(false), andthrow(), are supported; arbitrary expressions fornoexceptor types forthroware not. - C++ namespace alias declarations are not supported:
namespace ALN = A_Long_Name; // not supported
- Multiple
_Alignasoralignasspecifiers in the same declaration are not supported. - For the argument to either the
_Alignasoralignasspecifier, only integer literals or types are supported; arbitrary expressions are not. - Only simple C++ attribute specifiers like
[[this]]are supported; attribute specifiers with namespaces are not. Additionally, optional arguments fordeprecatedandnodiscardare ignored. - C++20 contracts (
[[assert]],[[ensures]], and[[expects]]) are not supported. - The C++20
explicitspecifier with an expression is not supported.
๐ Other Caveats
- Multi-line C-style comments can be used only on lines by themselves, or either before or after commands, but not within commands. ๐
- Macros are expanded only via the
expandcommand and can't be used elsewhere:
cdecl> #define exp explain
cdecl> exp int *p // error: can't alias commands
cdecl> #define FILE_PTR FILE*
cdecl> explain FILE_PTR f // error: can't use as type
- When converting from pseudo-English to a C++ declaration, any
enum,class,struct, oruniontype keyword omitted from a declaration (via omission from either the--explicit-ecsuor-Soption, or theset explicit-ecsucommand) makes the declaration not ``round-trippable'':
c++decl> declare pt as pointer to class T
T *pt;
c++decl> explain T *pt
^
18: error: "T": unknown name
This is because, when going from a C++ declaration to pseudo-English, cdecl doesn't know that an arbitrary name, in this example, T, is a class name.
To include the type keywords explicitly and thus make the declarations ``round-trippable,'' include them via either the --explicit-ecsu or -S option, or the set explicit-ecsu command. ๐
Alternatively, declare the type via one of class, define, enum, struct, typedef, union, or using:
c++decl> class T
c++decl> explain T *pt
declare pt as pointer to T
- While
class,enum,explain,namespace,struct,typedef,union, andusingcan accept names that arecdeclkeywords,cast,declare, anddefinecan not; hence, not all explanations are ``round-trippable'':
cdecl> explain int explain
declare explain as integer
cdecl> declare explain as integer
^
9: syntax error: "explain": name expected
- When converting from one of the C++ overloaded operators
&,*,+,++,-, or--, to pseudo-English when declared as:
T operator OP(U);
i.e., taking one parameter, it's ambiguous (to cdecl) between being a member or non-member operator since cdecl doesn't have the context in which the operator is declared. If it were declared in-class, e.g.:
class T {
public:
// ...
T operator OP(U);
};
then clearly it's a member operator; if it were declared at file scope, then clearly it's a non-member operator; but cdecl doesn't have this context. In such cases, cdecl omits either member or non-member from its output.
- When converting from pseudo-English to a C23 or C++11 declaration for
auto(or__auto_typein GNU C), a C++17 structured binding, or aconst,constinit, reference, or an rvalue reference variable that is not a function parameter, the output doesn't include an initializer:
c++decl> declare x as auto
auto x;
c++decl> declare x, y as structured binding
auto [x, y];
c++decl> declare r as reference to int
int &r;
These are illegal C++ declarations since such declarations must be initialized. ๐ฌ
- Only casting a name is supported; casting an expression is not.
- When converting from or to a C++ new-style cast, only some semantic validation is performed to determine whether the type of cast is legal.
- When a predefined type, e.g.,
size_t,uint16_t, etc., is shown (via theshowcommand), the underlying type is merely typical and does not necessarily match the underlying type on any particular platform or even the platform on whichcdeclis running. ๐ซ - An integer literal given as the argument for an alignment specifier is only checked to ensure it's either zero or a power of two; it is not checked to see whether it meets the minimum alignment for the type.
- In GNU C, the type
__int128is a distinct type; in Microsoft C, the types__int8,__int16,__int32,__int64, and__wchar_tare keyword synonyms. These types can take modifiers:
unsigned __int128 x128; // legal in GNU C
unsigned __int32 x32; // legal in Microsoft C
In cdecl, these types are typedefs and can't take modifiers since that's illegal in C.
- When using the
--linenoor-Loption with a here document containing escaped newlines (lines ending in\), the\s also need to be escaped to get the line numbers correct because the shell ordinarily strips escaped newlines; for example:
#define IDENT_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ_" \\
"abcdefghijklmnopqrstuvwxyz" \\
"0123456789"
๐ AUTHORS ๐
cdecl has been around since the mid-1980s and there have been many versions of cdecl, some with different subsets of authors. This list is a best-effort at a union of all authors. In reverse chronological order:
- Paul J. Lucas
<paul@lucasmail.org> - Peter Ammon
<cdecl@ridiculousfish.com> - David R. Conrad
<conrad@detroit.freenet.org> - Alexander Dupuy
<dupuy@cs.columbia.edu> - Merlyn LeRoy
<merlyn@rose3.rosemount.com> - Tony Hansen
<tony@attmail.com> - David Wolverton
<david_wolverton@att.com> - Graham Ross
๐ SEE ALSO ๐
bison(1), clang(1), flex(1), gcc(1), less(1), vi(1), yacc(1), isatty(3), readline(3), sysexits(3), editrc(5)
okay that's the whole page bestie, we did it!! ๐โจ this lil manual is from the PJL TOOLS era, dated February 20, 2026, and it lives under cdecl(1). go forth and declare things, you absolute icon ๐๐ฆ
๐ฆ where this page comes from
- fedora 43: cdecl 18.7.2-1.fc43 ยท GPL-3.0-or-later AND LGPL-2.1-or-later AND LicenseRef-Fedora-PublicDomain
- fedora 44: cdecl 18.7.2-1.fc44 ยท GPL-3.0-or-later AND LGPL-2.1-or-later AND LicenseRef-Fedora-PublicDomain
- nixpkgs unstable: cdecl 18.7.2
- Copyright (C) 2017-2026 Paul J. Lucas, et al
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms