Difference between single and double square brackets in autoconf - autoconf

So what is the difference between single and double square brackets in autoconf?
Autoconf docs show following example:
AC_CHECK_TYPES([float_t], [], [], [[#include <math.h>]])
IMHO it also works with single brackets:
AC_CHECK_TYPES([float_t], [], [], [#include <math.h>])

If you use [[ ]] for your macro argument, you can use [ and ] inside the macro argument as you please. If, on the other hand, you use [] for your macro argument, [ and ] retain their special autoconf/m4 meaning inside the macro argument.
The difference becomes obvious if the actual text in the macro argument contains brackets, e.g.
dnl Minimum working example configure.ac. To run:
dnl touch Makefile.am && autoreconf -vis . && ./configure
AC_PREREQ([2.69])
AC_INIT([stackoverflow53609622], [0.0.1], [bugs#example.com])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_MSG_CHECKING([compile example 1])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
const char hw[] = "Hello, World\n";
const char hs[] = "Hello, Stackoverflow\n";
]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
AC_MSG_CHECKING([compile example 2])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
const char hw[[]] = "Hello, World\n";
const char hs[[]] = "Hello, Stackoverflow\n";
])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
AC_MSG_CHECKING([compile example 3])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
const char hw[] = "Hello, World\n";
const char hs[] = "Hello, Stackoverflow\n";
])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Both examples 1 and 2 will test compile the C program
const char hw[] = "Hello, World\n";
const char hs[] = "Hello, Stackoverflow\n";
but example 3 will test compile the broken C program
const char hw = "Hello, World\n";
const char hs = "Hello, Stackoverflow\n";
which will not compile (see config.log for the compiler error messages).
If you put unbalanced brackets into the macro argument text, however, m4 will still become really confused about where macro arguments begin or end. AFAIK, the only way around that is to use quadrigraphs (#<:# for [ and #:># for ]):
AC_MSG_CHECKING([compile example 4])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
const char hw[] = "Hello, World #<:#-:\n";
const char hs[] = "Hello, Stackoverflow\n";
]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
AC_MSG_CHECKING([compile example 5])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
const char hw[] = "Hello, World :-#:>#\n";
const char hs[] = "Hello, Stackoverflow\n";
]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
The following will fail either at autoreconf or at configure time which indicates that something is going very wrong and you should steer very clear from that.
AC_MSG_CHECKING([compile example 6])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
const char hw[] = "Hello, World :-[\n";
const char hs[] = "Hello, Stackoverflow\n";
]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
AC_MSG_CHECKING([compile example 7])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
const char hw[] = "Hello, World :-]\n";
const char hs[] = "Hello, Stackoverflow\n";
]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
For further reading, you can start at https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/M4-Quotation.html and dig deeper from there.

Related

Have to count a character occurrence in Nim string type

How to count a character occurrence in string in Nim, mainly using its native statements prior go to module ? eg.
var
str = "Hello World"
c : int
c = numChar( "o", str ) # <- illustration only ?
The earlier answer is correct but if you do not want to import any modules you can write your own procedure:
proc count_char(value: string = "Hello World", ch: char = 'o'): int =
var cnt_c: int = 0
for c in value:
if c == ch:
cnt_c += 1
result = cnt_c
var
val: string = "Mother Goose"
ch: char = 'o'
echo $count_char(val, ch)
PS: Unrelated - Need syntax highlight for nim-lang on SO.
Use the count function from strutils:
import std/strutils
let str = "Hello World"
let count = count(str, 'o')
assert count = 1
There’s also a string overload for counting sub strings as well.

problems using demo arguments in c code do deal with the strings in argv

I have a c code to show a lowercase of one argument:
This code runs ok when called from commandline with more than 6 argument
however,if called without argument, the demo part does not work ,and programme got stuck:
Below is the code file:
Can anyone help me, Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctype.h>
int showLowerCase(char *argv[]){
char* aStr = argv[6];
//To lowercase: the demo got stuck probably here
for (int i = 0; aStr[i]; i++) {
aStr[i] = tolower(aStr[i]);
}
printf("a lower case for 6th input string: %s\n",aStr);
}
int main(int argc, char *argv[])
{
if(argc < 7){
// when no srguments given, try a demo:
// change argc to 7
argc = 7;
// make a example of argv2 with 7 strings
char *argv2[7];
argv2[0] = "killWindowsVersatile.exe";
argv2[1] = "key";
argv2[2] = "ci";
argv2[3] = "once";
argv2[4] = "2";
argv2[5] = "1000";
argv2[6] = "SuperCol"; //this argument will be shown as lowercase
showLowerCase(argv2);
return 0;
}
showLowerCase(argv);
return 0;
}
It seems that argv can be modified to lowercase in site, while the argv2 I constructed cannot be modified.
Solved by strcpy:
int showLowerCase(char *argv[]){
printf("aStr = argv[6]\n");
char* aStr = argv[6];
printf("aStr = argv[6]...done");
//make hard copy
char newStr[strlen(aStr)+1];
strcpy(newStr,aStr);
//To lowercase
for (int i = 0; newStr[i]; i++) {
printf("i=0\n");
printf("%c\n",newStr[i]);
newStr[i] = tolower(aStr[i]);
}
printf("a lower case for 6th input string: %s\n",newStr);
}

Failure to read a string using cin

For this simple piece of code:
#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::string;
bool are_uniq_chars(string const&);
int main(){
string s;
cout << "Enter string: ";
cin >> s;
auto flag = are_uniq_chars(s);
I get the following illegal value for s upon gdb debugging:
Thread 2 hit Breakpoint 1, main () at main.cpp:10
10 string s;
(gdb) n
11 cout << "Enter string: ";
(gdb) n
12 cin >> s;
(gdb) n
Enter string: vinod
13 auto flag = are_uniq_chars(s);
(gdb) p s
$1 = {<std::__1::__basic_string_common<true>> = {<No data fields>},
__r_ = {<std::__1::__libcpp_compressed_pair_imp<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, std::__1::allocator<char>, 2>> = {<std::__1::allocator<char>> = {<No data fields>},
__first_ = {{__l = {__cap_ = 110429756552714, __size_ = 0,
__data_ = 0x0}, __s = {{__size_ = 10 '\n', __lx = 10 '\n'},
__data_ = "vinod", '\000' <repeats 17 times>}, __r = {__words = {
110429756552714, 0, 0}}}}}, <No data fields>},
static npos = 18446744073709551615}
Not sure what is wrong? The code is being run on macOS High Sierra 10.13.2.
Any help would be appreciated.
TIA
Vinod
Guess this output is normal as the program started working as expected after fixing another error.

Non-visible char in const char * as strtok() delimiter

I had to split the payload of network data by the "new line" or "line feed" character (dec 10, hex 0x0A).
So i tried to use strtok() function with which i encountered several problems
when i wanted to make a const char string with the "new line" character.
Proto:
`strtok(char * StringToSplit, const char * Delimiters)`
This made an invalid initializer:
`const char delim[] = 10;`
This gave warning about making pointer from int without cast;
Allthough
printf("Delim: %x", delim)
showed correct value of delim (0xa)
the app crashes when used in strtok().
`const char * delim = 10;`
No warning or errors, printf("Delim: %x", delim) gave correct value
but strtok() didn't work (as i expected, though).
`char delim = 10;`
`(ofc strtok(..., &delim))`
This seemed to do the job but i still got a warning about passing a non const char ptr where a const char ptr was expected to strtok() function.
`char delim[] = "#";`
`delim[0] = 10;`
Finally this seems to work without warnings.
`char tmp[] = "#";`
`tmp[0] = 10;`
`const char *delim = tmp;`
Question is, what would be the simplest and most elegant way to pass such a non-visible character to the strtok() function?
To me it feels like this is just kludged code.
You need:
const char *delim = "\n";
The second parameter needs to be a C string containing the delimiters. What you have in your various incarnations are lots of things that aren't C strings being incorrectly cast to C strings.
It's not kludged or inelegant, it's just got lots of bugs.
const char delim[] = 10;
Why are you declaring an array here? This should be:
const char delim = 10;
And then:
char delim[] = "#";
Why are you declaring an array and setting it equal to a string? This shuld be:
char delim = '#';

Weird define in C++ preprocessor

I've come across this
#define DsHook(a,b,c) if (!c##_) { INT_PTR* p=b+*(INT_PTR**)a; VirtualProtect(&c##_,4,PAGE_EXECUTE_READWRITE,&no); *(INT_PTR*)&c##_=*p; VirtualProtect(p,4,PAGE_EXECUTE_READWRITE,&no); *p=(INT_PTR)c; }
and everything is clear except the "c##_" word, what does that mean?
It means to "glue" together, so c and _ get "glued together" to form c_. This glueing happens after argument replacement in the macro. See my example:
#define glue(a,b) a##_##b
const char *hello_world = "Hello, World!";
int main(int arg, char *argv[]) {
printf("%s\n", glue(hello,world)); // prints Hello, World!
return 0;
}
It is called a token-pasting operator. Example:
// preprocessor_token_pasting.cpp
#include <stdio.h>
#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;
int main()
{
paster(9);
}
Output
token9 = 9
That's concatenation that appends an underscore to the name passed as c. So when you use
DsHook(a,b,Something)
that part turns into
if (!Something_)
After the preprocessor, your macro will be expanded as:
if (!c_) { INT_PTR* p=b+*(INT_PTR**)a; VirtualProtect(&c_,4,PAGE_EXECUTE_READWRITE,&no); *(INT_PTR*)&c_=*p; VirtualProtect(p,4,PAGE_EXECUTE_READWRITE,&no); *p=(INT_PTR)c; }
The ## directive concatenates the value of c which you pass as a macro parameter to _
Simple one:
#define Check(a) if(c##x == 0) { }
At call site:
int varx; // Note the x
Check(var);
Would expand as:
if(varx == 0) { }
It is called Token Concatenation and it is used to concatenate tokens during the preprocessing
For example the following code will print out the values of the values of c, c_, c_spam:
#include<stdio.h>
#define DsHook(a,b,c) if (!c##_) \
{printf("c=%d c_ = %d and c_spam = %d\n",\
c, c##_,c##_spam);}
int main(){
int a,b,c=3;
int c_ = 0, c_spam = 4;
DsHook(a,b,c);
return 0;
}
Output:
c=3 c_ = 0 and c_spam = 4

Resources