Format of structs using emacs c code auto-newline - c

I have recently started using emacs for editing C source, and have been using the auto-newline feature of cc-mode (c-toggle-auto-newline). This works well for constructs like functions and if/else statements, but seems to act strangely when a closing brace should be followed by a semi-colon.
Using auto-newline in GNU Emacs 23.3 I get:
struct foo
{
int x;
}
;
char int[2] =
{
0, 1
}
;
I would like to instead get:
struct foo {
int x;
};
char int[2] = { 0, 1 };
How can I get the closing semi-colon to remain on the same line as the closing brace?

I don't think you can go around this problem with auto newline on. It's not a greatly thought-through feature, it simply inserts newlines after certain characters (;, {, etc.). But seriously, how hard is it to press and enter key? Any automation is always error-prone.

You can customize the "cleanup" behavior when auto-newline is turned on. This is controlled by the contents of the c-cleanup-list variable. (View help for this within Emacs by entering C-h v c-cleanup-list.
Specifically, adding defun-close-semi to c-cleanup-list will solve your problem.
If you're already defining a custom style within your ~/.emacs file, then you can probably figure out how to do this. Otherwise, the easiest way to change this setting is via Customize. In the help buffer (displayed when you ran C-h v c-cleanup-list), the last line will have a link to customize this variable.

Related

Visual Studio Open Folder GCC (Cygwin) Intellisense Errors

I'm trying to configure Visual Studio Community 2019 for use as the IDE for work on an open source C project targeting the Nintendo 64.
The makefile seems to define a gcc-derivative (mips64-elf-gcc) as the compiler and has -std=gnu99 as one of the CFLAGS, so I assume that means this is C99.
I don't know much about C development, so I initially followed a tutorial, which directed me to set up Cygwin. For a time I edited the *.h and *.c files in Notepad++ and then used the Cygwin terminal to compile everything (there's probably a thousand better ways, but I'm a C/*nix nub and just wanted to get something off the ground quickly). Notepad++ was ok just to tinker around with things, but I'm getting more serious about this project and doing any real work in Notepad++ is a real bother. I've used Visual Studio for a long time, so I figured I'd try getting things set up there, since I know it has support for C/C++.
I've successfully gotten VS to run my makefile using the "Open Folder" feature and by wiring up the requisite data within the CppProperties.json and tasks.vs.json files. While attempting to get IntelliSense working, however, I've run into a few errors that I can't resolve.
1. 'duplicate parameter name' in stdio.h & string.h
There are several instances of this error. The problem seems to be lines like this one:
FILE * freopen (const char *__restrict, const char *__restrict, FILE *__restrict);
As you can see, there are multiple "parameters" all named __restrict. I'm still just beginning my C journey, so I'm not entirely sure what this is, but my suspicion was that it wasn't a parameter name, but might be #defineed somehwere. Using the Agent Ransack file search utility, I looked for instances of #define __restrict and did find some. I added those paths to the INCLUDE section of my CppProperties.json file, but that didn't help at all.
According to the VS Open Folder tutorial, IntelliSense can sometimes get hung up on preprocessor directives, so I added the recommended cpp.hint file, closed VS, deleted cached data in the .vs folder, and started VS back up, but the errors still persist.
2. "expected a ')'" in stdio.h
I assume this one is also related to that __restrict issue.
FILE * fopen (const char *__restrict _name, const char *__restrict _type);
^
| expected a ')'
It seems to be unhappy about the _name parameter for some reason.
3. 'expected an expression / identifier "i" is undefined' in my for loops
Any place in the code I've been working on where a for loop is defined, I get these errors. Here's an example of the errors:
void v(void)
{
for (int i = 0; i < 25; i++)
{ ^ ^
| | identifier "i" is undefined
|
| expected an expression
}
}
If, however, I change the loop to the following, everything is fine.
void v(void)
{
int i;
for (i = 0; i < 25; i++)
{
}
}
It's not liking the int type declaration in in the init-expression of the for loop. I'm not sure what I could've done in configuration to break a core language feature. I assume something about the previous errors are affecting this.
None of this affects the build process, since all of that is still being done through the makefile using everything I have set up in Cygwin, so I guess it isn't critical to fix these issues, but the whole point of doing this was to have a nice environment to work in and having 61 errors constantly hanging out is probably gonna put a pretty big damper on that situation.
I've tried everything I can think of to resolve these issues and nothing has worked. This is a particularly difficult issue to google, due to the large number of potential contributing factors required as search terms, so that hasn't proved fruitful.
Any help or advice is appreciated.

C/C++ BEGINNER - fgets with stdin causing unexpected 'loop' results

I'm a programming student who's only really looked at Java up until now. This semester is our first time using C and I'm having a lot of trouble wrapping my head around some of the simplest functions. I really have no idea what I'm doing. I couldn't even get Eclipse to work correctly with MinGW so I eventually gave up and reverted to Netbeans.
So basically I'm trying to use fgets to read user input for a switch-case menu, but I can't get fgets to work in even the simplest situations. To troubleshoot I tried copying a simple fgets example from online, but even that is giving me unexpected results.
When I run the code below it just runs an infinite empty loop (it does not prompt for user entry at all, it does not accept any user entry, it just 'runs' forever and the console remains blank). When I delete the fgets line and remove the other reference to the 'name' variable it works as you would expect (prints the user entry prompt and then ends).
Example code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
char name[10];
printf("Who are you? ");
fgets(name,10,stdin);
printf("Glad to meet you, %s.\n",name);
return(0);
return (EXIT_SUCCESS);
}
Any advice would be appreciated!
Other info:
I am running - Win 8 (poor me) & Netbeans IDE 8.0 (with MinGW)
When creating my C project I select File=> New Project=> C/C++=> C/C++ Application
EDIT: When I run the program I have tried:
1) right clicking the project file => Run; and
2) clicking the big green arrow in the netbeans ribbon;
.... neither works.
This code should work, but for you to be able to input anything, you need to run in in a proper terminal.
My guess is that you're running it inside your IDE and it's set to use pipes as stdin/stdout. Instead you should start cmd.exe and run the program in there (you'll have to navigate to the correct directory first).
Or, optionally, there might be a setting in your IDE to run the program using cmd.exe or with a builtin terminal.
A final note. You should learn to use sizeof whenever a buffer size is required. I.e. change this:
fgets(name,10,stdin);
to
fgets(name, sizeof(name), stdin);
Also, please use spaces to make your code more readable. Reading code is a big part of programming.
1) You might want to flush the file, after printf("Who are you? "); with fflush(stdout);
2) You have two return statements (which is harmless).
Other than that, your code is fine.
It works perfect - but you might want using fflush(stdin); before the fgets() call.
Also remember fgets return a string with '\n' after a user input - solved simply with name[strlen(name)-1]='\0'; - which is basically putting NULL as an "end of a string" symbol, basically you remove the '\n'.
And DO NOT change 10 to sizeof(name) - it doesn't matter at all, basically it's even supposedly worse as you can't use this in functions properly (sizeof(name) won't always match the length and would be the size of the pointer).
You should try compiling with MinGW if it didn't work, it will surely work on it.
A reminder: fgets() may let you enter MILLION characters, but it will take the first 10, in this case, at least.

Hard wrap string literals at print margin in Eclipse C/C++

C/C++ Eclipse can automatically format and wrap just about any kind of code and behaviour is very configurable, except for string literals. Here is a made up example where debug output message happens to be longer than what can fit within a printable area:
if (some_kind_of_action() == TOUGH_LUCK) {
system_debug_print("Task name error: some_kind_of_action() failed due to your sloppy design.");
}
Using 79 character print margin the desirable result could be:
if (some_kind_of_action() == TOUGH_LUCK) {
system_debug_print("Task name error: some_kind_of_action() failed due to yo"
"ur sloppy design.");
}
You can do this manually by typing your string literal, then placing cursor at the desirable wrap point and pressing Enter key. Eclipse will automatically add necessary quotation marks. This is all nice, until something in your code changes and you have to manually redo the wrapping. I don't see why wrapping at print margin can't be done fully automatically like any other piece of code.
Is there any way to automate hard wrapping of string literals at print margin in Eclipse for C/C++?
Eclipse does not support this feature in any of its editors (even though it was requested nine years ago). However you may be able to avoid breaking your lines manually by using the following plugin for enabling soft wrap.
http://ahtik.com/blog/projects/eclipse-word-wrap/

How can I autoformat/indent C code in vim?

When I copy code from another file, the formatting is messed up, like this:
fun()
{
for(...)
{
for(...)
{
if(...)
{
}
}
}
}
How can I autoformat this code in vim?
Try the following keystrokes:
gg=G
Explanation: gg goes to the top of the file, = is a command to fix the indentation and G tells it to perform the operation to the end of the file.
I like to use the program Artistic Style. According to their website:
Artistic Style is a source code indenter, formatter, and beautifier for the C, C++, C# and Java programming languages.
It runs in Window, Linux and Mac. It will do things like indenting, replacing tabs with spaces or vice-versa, putting spaces around operations however you like (converting if(x<2) to if ( x<2 ) if that's how you like it), putting braces on the same line as function definitions, or moving them to the line below, etc. All the options are controlled by command line parameters.
In order to use it in vim, just set the formatprg option to it, and then use the gq command. So, for example, I have in my .vimrc:
autocmd BufNewFile,BufRead *.cpp set formatprg=astyle\ -T4pb
so that whenever I open a .cpp file, formatprg is set with the options I like. Then, I can type gg to go to the top of the file, and gqG to format the entire file according to my standards. If I only need to reformat a single function, I can go to the top of the function, then type gq][ and it will reformat just that function.
The options I have for astyle, -T4pb, are just my preferences. You can look through their docs, and change the options to have it format the code however you like.
Here's a demo. Before astyle:
int main(){if(x<2){x=3;}}
float test()
{
if(x<2)
x=3;
}
After astyle (gggqG):
int main()
{
if (x < 2)
{
x = 3;
}
}
float test()
{
if (x < 2)
x = 3;
}
The builtin command for properly indenting the code has already been mentioned (gg=G). If you want to beautify the code, you'll need to use an external application like indent. Since % denotes the current file in ex mode, you can use it like this:
:!indent %
I find that clang-format works well.
There are some example keybindings in the clang documentation
I prefer to use the equalprg binding in vim. This allows you to invoke clang-format with G=gg or other = indent options.
Just put the following in your .vimrc file:
autocmd FileType c,cpp setlocal equalprg=clang-format
The plugin vim-autoformat lets you format your buffer (or buffer selections) with a single command: https://github.com/vim-autoformat/vim-autoformat. It uses external format programs for that, with a fallback to vim's indentation functionality.
I like indent as mentioned above, but most often I want to format only a small section of the file that I'm working on. Since indent can take code from stdin, its really simple:
Select the block of code you want to format with V or the like.
Format by typing :!indent.
astyle takes stdin too, so you can use the same trick there.
I wanted to add, that in order to prevent it from being messed up in the first place you can type :set paste before pasting. After pasting, you can type :set nopaste for things like js-beautify and indenting to work again.
Maybe you can try the followings
$indent -kr -i8 *.c
Hope it's useful for you!
Their is a tool called indent. You can download it with apt-get install indent, then run indent my_program.c.
For a good overview and demo of many of the options mentioned here, #Gavin-Freeborn has a great video on YouTube:
https://www.youtube.com/watch?v=tM_uIwSucPU
It covers some Vim plugins as well as built-in capabilities such as =, gq, and formatprg.

Emacs comment-region in C mode

In GNU Emacs, is there a good way to change the comment-region command in C mode from
/* This is a comment which extends */
/* over more than one line in C. */
to
/* This is a comment which extends
over more than one line in C. */
? I have tried
(setq comment-multi-line t)
but this does not help. There is a section on multi-line comments in the Emacs manual, but it does not mention anything.
Since Emacs 21, there's been a module named 'newcomment, which has different comment styles (see the variable 'comment-styles. This setting gets close to what you want:
(setq comment-style 'multi-line)
(Note: you should probably make that setting in 'c-mode-hook).
However, none of the settings make the comments look like what you want.
The easiest way I saw to get what you want is to add this hack:
(defadvice comment-region-internal (before comment-region-internal-hack-ccs activate)
"override 4th argument to be just spaces"
(when (eq major-mode 'c-mode) ; some condition here
(let ((arg (ad-get-arg 4)))
(when arg
(ad-set-arg 4 (make-string (length arg) ?\ ))))))
The current settings for comment-style always prefix the comment lines with " * " (if not the whole " /* ").
If you don't have Emacs 21, I suppose you could simply download newcomment.el from the repository. I don't know if it works as-is in earlier versions of Emacs, but it might be worth a shot, though upgrading Emacs would be a better solution.
My hack breaks the 'uncomment-region. A proper fix would be to change 'comment-padright. That would take a little more research so as not to break other things. The above hack only changes behavior in 'c-mode (adjust the condition to your liking).
Closest I could find with the built-in commenting support is if you set comment-style to multi-line, which will produce this:
/* This is a comment which extends
* over more than one line in C. */
If that isn't close enough, take a look at newcomment.el and define your own commenting functions as appropriate.

Resources