Roadside Picnic :::
  • Friends
  • About
  • Categories
  • Tags

>> Home / Posts / Computer

Cdecl, Vim, function pointers, and you

Casting for novices

If you’re learning C/C++ or working on a codebase with some absolutely psychotic casting, you might have come across this site

https://cdecl.org/


The site is nice and approachable, look at this default example:


int (*(*foo)(const void *))[3]


Which is then turned into something that almost resembles english.


declare foo as pointer to function (pointer to const void) returning pointer to array 3 of int


But, soon you’ll try to put one of the types in <stdint.h> into the text box and hit a roadblock


uint32_t (*(*foo)(const void *))[3]
syntax error


What's the deal? Where are my beautiful int#_t style units? Unfortunately the website seems to be using an older version of cdecl, and we've generated some new types of gibberish since that version was written.

Have no fear, you can get a modern up to date version, and even hook it into your vim! Make sure you have the following installed first:

  • -autoconf
  • -automake
  • -m4
  • -flex
  • -bison

Odds are that most of these are already somewhere on your linux system.

Run the following commands in a convenient directory.

(‘$’ denotes a command you type)


$ git clone https://github.com/paul-j-lucas/cdecl.git
$ cd cdecl
$ ./bootstrap
$ ./configure
$ sudo make install

Now try the cdecl command and you should be greeted to this screen:


$ cdecl
Type "help" or "?" for help
cdecl> 
cdecl> explain uint32_t (*(*foo)(const void *))[3]
declare foo as pointer to function (pointer to constant void) returning pointer to array 3 of uint32_t


Success! This version supports the typedefs you’d expect to see in the wild, as well as allowing you to add your own typedefs, declarations, macros, and much more.

The command line interface is great on it’s own, but it might be nice to access this without leaving our editor.

You can get the vim plugin packaged in vimball form from this beautiful website:

DRCHIP’S VISCDECL


But to install it, make sure you pick up the Vimball Archiver as well:

DRCHIP’S VIMBALL


Extract the vimball tar file and edit it’s permissions:


$ gunzip vimball.tar.gz
$ tar -oxvf vimball.tar
plugin/vimballPlugin.vim
autoload/vimball.vim
doc/pi_vimball.txt
$ chmod a+r autoload/vimball.vim doc/pi_vimball.txt plugin/vimballPlugin.vim


You likely have pathogen managing the ~/.vim/bundle directory, so lets move the vimball plugin there


$ mkdir ~/.vim/bundle/Vimball
$ mv -t ~/.vim/bundle/Vimball autoload/vimball.vim doc/pi_vimball.txt plugin/vimballPlugin.vim


Now make sure that the following lines are in your .vimrc file


set nocp
filetype plugin on



Next unzip your VisCdecl.vba.gz


$ gunzip VisCdecl.vba.gz
$ vim VisCdecl.vba


Unfortunately, it seems like the plugin doesn’t quite work anymore, vimscript is a bit hard to debug so here’s how I managed to fix it, go to ~/.vim/ftplugin/c/VisCdecl.vim and replace the VisCdecl() with the code below:


" ----------------------------------------------------------------
" VisCdecl: appends a comment explaining the declaration {{{1
fun! s:VisCdecl()
  if !executable("cdecl")
   redraw!
   echohl WarningMsg | echo "sorry, can't find cdecl on your system" | echohl None
   return
  endif
  let curline = getline(".")
  let curline = substitute(curline,'^',"cdecl explain \'",'') . "\'"
  let curline = substitute(curline,'\s*= .*;',';','')
  let akeep   = @a
  let @a      = curline
  let @a = trim(system(@a))
  put a
  s/^.*$/\/* & *\//
  norm! kJ
  let @a=akeep
endfun

" ----------------------------------------------------------------

Note the system() call, if that give you the heebie jeebies, you probably know enough to come up with your own fix, but this is good enough for me.

This plugin is set to work on .c files, you can set a new buffer to be recognized as a .c file with


:set filetype=c



To use the plugin set your cursor the line you want to translate and enter visual mode with ‘v’ or ‘V’ and press Ctrl+F1 to run VisCdecl()


int myint= 0; 
int myint= 0; /* declare myint as integer */
uint32_t (*(*foo)(const void *))[3] 
uint32_t (*(*foo)(const void *))[3] /* declare foo as pointer to function (pointer to constant void) returning pointer to array 3 of uint32_t */

Happy Coding!

∵ Redrick Schuhart ∴ 2025-04-08

  • Photo
  • Posts

  • Computer

2025 © Redrick Schuhart | Built with Blades | No JavaScript used | About