How can I evaluate VS build command macros? - visual-studio

It's more often obvious what a build command macro like $(SolutionDir) will evaluate to, but when building complex strings of these macros, it would be nice to be able to quickly evaluate the resulting real string. Is there any way of doing this except building a custom tool that takes a string of macros as input and outputs the evaluated string?

Just add a pre-build event and use "echo" to display the string in the Output window
echo $(SolutionDir)

Related

How do I debug vim indentexpr script?

I have downloaded a verilog/systemverilog indent file which looks really comprehensive. However, there is a problem: it doesn't work. I'm looking at the vimscript code and want to both fix it (I'm on vim 8.2, maybe there's a version mismatch) as well as enhance it. However, I'm running into issues debugging. Specifically, indentexpr scripts have a variable v:lnum which is set when indentkey is pressed and the indentexpr is evaluated.
BUT, I don't know of a way to enter debug mode on just the indentexpr call. I tried manually calling the function inside the vimscript but that leaves v:lnum as some garbage number (well, the last line to invoke indentexpr). Is there a way to enter debug mode when I actually hit a key that invokes indentexpr?
The best way for v:lnum to be used is as an argument to the function. Here's an example: vim-ruby's indentexpr setting used to look like this:
setlocal indentexpr=GetRubyIndent()
Inside the function, the variable v:lnum was used to get the line number that it was called on. This, as you've discovered, is pretty inconvenient. So, the better way is:
setlocal indentexpr=GetRubyIndent(v:lnum)
So, find the place in the script where the indentexpr is set and change it to take the magic v:lnum variable as an argument. You could then rewrite the function itself to take a single argument:
function! GetRubyIndent(lnum)
Now, in that function, the a:lnum variable will be the line number, and you can call the function with that argument. Search-and-replace v:lnum with a:lnum everywhere in the function. The indent script should now work as it did before, and you'll be able to call the function manually with a line number.
Here's the specific commit that does this in the vim-ruby repository, as an example
Additionally, echomsg "foo" will print a message that you can read afterwards by running the :messages command. And I can recommend the Decho plugin for easy-to-read debug messages.

How can I refer to F# names containing a single quote in a C# context?

This mostly comes up while trying to debug F# code in the Visual Studio debugger, which expects C# syntax:
The debugger does not recognize F# expressions. To enter an expression in a debugger window or a dialog box during F# debugging, you must translate the expression into C# syntax. When you translate an F# expression into C#, make sure to remember that C# uses == as the comparison operator for equality and that F# uses a single =.
(from http://msdn.microsoft.com/en-us/library/vstudio/ee843932.aspx)
The problem is that I have variables and functions that contain single quote characters, like path', but single quotes seem not to be valid in names in C#, so entering path' in the debugger window just says Newline expected in constant or words to that effect, because it thinks I am starting a character literal. Even right-clicking on it and adding a watch via the contextual menu gives a similar error.
How can I translate F# names containing single quotes into C# syntax, so that I can inspect them from the debugger or refer to them from C# code?
I do not think there is a way to do this - so the best option is probably to rename the variable path' to some other name that is a valid C# identifier like pathAux.
Although F# is more flexible with naming (and allows things like path' or even ``whatever !``), it is probably a good idea to use C#-compatible identifier names most of the times, because it will make the code readable to a wider audience - such as C# developers.

Accessing Visual Studio macros from source code?

Visual Studio has macros like $(TargetDirectory), $(OutputPath) etc.
In my source code, I want to specify a relative path for the loading of a file from a folder a few levels below the TargetDirectory.
Currently I'm doing this: mLayer = mEngine->AddLayer("D:\\Projects\\abc.osg"); and I want it to be something like mLayer = mEngine->AddLayer(($TargetDirectory)+"..\\..\\abc.osg");
It's just a temporary requirement, so that I can give my code to a person for a small demo, and his TargetDirectory is differently aligned wrt my directories. Is there any way to make use of the Visual Studio macros in source code? (at least I know that System environment variables can be accessed)
Go to Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions and add the following:
TARGET_DIRECTORY=LR"($(TargetDir))"
This defines a wide string literal named TARGET_DIRECTORY that contains the contents of the $(TargetDir) macro. The important thing here is that this creates a C++ raw string that does not treat backslashes as escape characters. Paths contain backslashes. Using a regular string literal would be incorrect and would even give you compiler errors in some cases.
Important!
If you use a macro that may contain a closing parenthesis followed by double quotation marks )" you must use an additional delimiter, that cannot occur in the macro value, for example:
TARGET_DIRECTORY=LR"|($(TargetDir))|"
In the case of windows file system paths this is not necessary because paths cannot contain double quotation marks.
You cannot do this automatically, but you can pass specific MSBuild properties to the preprocessor:
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>TARGET_DIRECTORY="$(TargetDirectory)"</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
This can be configured in the IDE by going to the Project Property Pages dialog, browsing to Configuration Properties -> C/C++ -> Preprocessor Definitions, and adding
TARGET_DIRECTORY="$(TargetDirectory)"
Note that your use of + for string literal concatenation is incorrect: string literals (and C Strings in general) cannot be concatenated using +. Rather, string literals can be concatenated simply by placing them adjacent to each other. For example,
TARGET_DIRECTORY "..\\..\\abc.osg"
Inside Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor you can add your directive.
PROJECT_DIR=R"($(ProjectDir))"
In code you can use it like.
std::string com = "powershell groovy "PROJECT_DIR"generate_report.groovy " + EXE_DIR;
EXE_DIR is a string in our case.
I'd suggest making these relative to the application's working directory, or something. Perhaps check out the GetCurrentDirectory function, at http://msdn.microsoft.com/en-us/library/aa364934%28v=vs.85%29.aspx.
Not that I know of but I have an alternative.
Deploy your file as a post build step. In this step you can consume the $(OutDir) macro which represents your binaries drop folder. This should help you place this file at a relative position from your app and use that relative position within your code.
This will also be a lasting solution rather than something done temporarily.
use TARGET_DIRECTORY=""$(TargetDir)"" instead of TARGET_DIRECTORY="$(TargetDir)" for string macro. (Note double quotes)
Worked for me in VS2005.

Single quotes and double quotes: How to have the same behaviour in unix and windows?

I have a batch script that call an exe with some parameters.
Currently I was passing the parameters to my exe like that:
$>my_cmd.exe %*
One of the options of the my_cmd.exe program takes arguments that can contain spaces
$>my_cmd.bat --req "in: lava" (OK my prog receives in: lava)
$>my_cmd.bat --req 'in: lava' (NOK my program receives 'in: lava')
Users use indifferently single quotes or double quotes.
It works with double quotes because they are eaten at the batch script level but when they use ' (single quotes) it is left and passed to my program.
my_cmd is multiplatform and on unix both single quote and double quote are special characters.
I would like to avoid having to do something specific in my_cmd program depending on the platform.
Is there a way to have the same behaviour in shell scripts and batch scripts.
For example the batch script could eat single quote if they are present ?
Tell me what would be the best solution for you.
Many thanks
On Windows, argument handling (and rules for quoting, globbing, etc) is the responsibility of the application. If your code uses anything except a single string containing all parameters with quotes intact, understand that this is because your development tools have done some preprocessing on the result of GetCommandLine. Therefore, for different quote handling, you need to look at your development tools, not at the OS. The best option is often to call GetCommandLine yourself and use your choice of library for processing it, instead of the one provided with your compiler.
That said, the Windows shell team has provided one of these libraries. See CommandLineToArgvW. But this is not part of the core OS, and using it is completely optional.
In addition, the batch processor does consider quotes when doing variable substitution. And that behavior is hard to change or disable, but it doesn't sound like it is the source of your problems.
Why not just change quotes to double?
set args=%*
my_cmd.exe %args:'="%

Shell scan for variables in "C" source program

Can anyone help me with some advice on how to solve the following problems?
The idea of the problem is to scan a Foo.c file to find all variables, how many times they occur, and the lines were they do occur.
The implementation can be in at least one of the methods:
Build a bat script and eventually additional C program(s)
to solve the problem. Run the implementation in a cmd window.
Build a ps1 script and eventually additional C program(s)
to solve the problem. Run the implementation in a PowerShell window.
I think that, in order to get all variable declarations and uses, and only variable declarations and uses, you're going to need to at least partially parse the source files and analyze the resulting abstract syntax trees.
Your first step, then, is to either write a parser or figure out how to utilize an existing one.
If you are programming C# you can use ANTLR V3 to parse your sources the "C" grammar exists.
You could certainly try to write this as a bat script, but believe me, I've written close to 200 bat scripts and it's horrendous. cmd.exe's findstr would be your friend, but between bat and regex, you're gonna go crazy. Powershell would definitely be better, however a real scripting language would be your best bet, like perl, ruby, or python.
Luckily, in your case anyways, all var in C are explicitly declared, so you could scan once for all the var declarations and create an array of them. Then, scan a second time looking for instances of those variable names. Total number of instances would be total_times_seen -1 since the first would be the var declaration. This assumes of course they are only declared once...

Resources