Strange outputs from DocOpt in Julia - command-line-arguments

From the docs, I've installed the DocOpt with Pkg.add("DocOpt") and created the same naval_fate.jl:
doc = """Naval Fate.
Usage:
naval_fate.jl ship new <name>...
naval_fate.jl ship <name> move <x> <y> [--speed=<kn>]
naval_fate.jl ship shoot <x> <y>
naval_fate.jl mine (set|remove) <x> <y> [--moored|--drifting]
naval_fate.jl -h | --help
naval_fate.jl --version
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
"""
using DocOpt # import docopt function
arguments = docopt(doc, version=v"2.0.0")
dump(arguments)
But when I run julia naval_fate.jl ship new FOO, I didn't dump the results as shown in the documentation. I got this instead:
Dict{AbstractString,Any}
slots: Array{UInt8}((64,)) UInt8[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 … 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01]
keys: Array{AbstractString}((64,))
1: #undef
2: #undef
3: #undef
4: #undef
5: #undef
...
60: #undef
61: #undef
62: SubString{String}
string: String " ( ship new <name> ... ) | ( ship <name> move <x> <y> [ --speed=<kn> ] ) | ( ship shoot <x> <y> ) | ( mine ( set | remove ) <x> <y> [ --moored | --drifting ] ) | ( -h | --help ) | ( --version ) "
offset: Int64 58
endof: Int64 3
63: #undef
64: SubString{String}
string: String "--speed <kn>"
offset: Int64 0
endof: Int64 7
vals: Array{Any}((64,))
1: #undef
2: #undef
3: #undef
4: #undef
5: #undef
...
60: #undef
61: #undef
62: Void nothing
63: #undef
64: SubString{String}
string: String "Naval Fate.\n\nUsage:\n naval_fate.jl ship new <name>...\n naval_fate.jl ship <name> move <x> <y> [--speed=<kn>]\n naval_fate.jl ship shoot <x> <y>\n naval_fate.jl mine (set|remove) <x> <y> [--moored|--drifting]\n naval_fate.jl -h | --help\n naval_fate.jl --version\n\nOptions:\n -h --help Show this screen.\n --version Show version.\n --speed=<kn> Speed in knots [default: 10].\n --moored Moored (anchored) mine.\n --drifting Drifting mine.\n\n"
offset: Int64 379
endof: Int64 2
ndel: Int64 0
count: Int64 15
age: UInt64 27
idxfloor: Int64 1
maxprobe: Int64 4
The output shown on the documentation is:
$ julia naval_fate.jl ship new FOO
Dict{String,Any} len 15
remove: Bool false
--help: Bool false
<name>: Array(UTF8String,(1,)) UTF8String["FOO"]
--drifting: Bool false
mine: Bool false
move: Bool false
--version: Bool false
--moored: Bool false
<x>: Nothing nothing
ship: Bool true
new: Bool true
...
Why is that so? Is it because of some cached session?

Related

Mimetex installation on Windows 7

I'm trying to install mimetex on Windows 7. To achieve this, I installed first cygwin on my machine, and then in the prompt window I typed:
gcc -DAA -DWINDOWS mimetex.c gifsave.c -lm -o mimetex.exe
in the right directory.
In the prompt I read:
but the exe was anyway created. When I tried to launch that exe, I saw this error:
Could it be some incompatibility with my Windows version? If yes, how can I solve?
Thanks in advance.
mimetex is using strcasestr that is not C standard and not available in every platform.
Taking the example code from How does strcasestr in C work. Keep getting Error external symbol
and putting in a strcasestr.c file we have
$ cat strcasestr.c
#include <stdlib.h>
#include <ctype.h>
char *strcasestr(const char *str, const char *pattern) {
size_t i;
if (!*pattern)
return (char*)str;
for (; *str; str++) {
if (toupper(*str) == toupper(*pattern)) {
for (i = 1;; i++) {
if (!pattern[i])
return (char*)str;
if (toupper(str[i]) != toupper(pattern[i]))
break;
}
}
}
return NULL;
}
and we can now compile with a lot of warning:
$ x86_64-w64-mingw32-gcc -Wall -DWINDOWS -DAA mimetex.c gifsave.c strcasestr.c -lm -o mimetex.cgi
mimetex.c: In function ‘rastsmash’:
mimetex.c:2384:26: warning: variable ‘ymin’ set but not used [-Wunused-but-set-variable]
....
mimetex.c:16687:2: warning: variable ‘isqempty’ set but not used [-Wunused-but-set-variable]
isqempty = 0, /* true if query string empty */
^~~~~~~~
$ ls -l mimetex.cgi
-rwxr-xr-x 1 Marco Kein 1.8M Jan 1 08:31 mimetex.cgi
Testing it in a CMD session, you can verify as suggested by the README that it is a stand alone windows program:
>mimetex.cgi "x^2+y^2"
+-----------------------------------------------------------------------+
|mimeTeX vers 1.75, Copyright(c) 2002-2017, John Forkosh Associates, Inc|
+-----------------------------------------------------------------------+
| mimeTeX is free software, licensed to you under terms of the GNU/GPL, |
| and comes with absolutely no warranty whatsoever. |
| See http://www.forkosh.com/mimetex.html for details. |
+-----------------------------------------------------------------------+
Most recent revision: 10 June 2017
Ascii dump of bitmap image...
.................***......................................***...
................*...*....................................*...*..
...............**...**..................................**...**.
...............**....*..................................**....*.
....................**...........*...........................**.
....................**...........*...........................**.
....................*............*...........................*..
....**..****.......*.............*...........**.....*.......*...
...*..**...*......*..............*..........*.*.....*......*....
..*...*..........*...*...........*..........*.*.....*.....*...*.
..*...*.........*....*...........*..........*.*.....*....*....*.
.....*.........*******....***************....*.....*....*******.
.....*...........................*...........*.....*............
.....*....*......................*...........*.....*............
.....*....*......................*...........*....**............
*...**...*.......................*...........*...**.............
.***..***........................*............***.*.............
.................................*................*.............
.................................*...............*..............
............................................*...*...............
.............................................***................

Can GNU as process struct and function prototypes in assembly file(.s)?

As we know, assembly files(.S) would get preprocessing before assembling, but I found that after preprocessing there may be struct/function prototypes in the resulting assembly files, How would the gnu as deal with these prototypes? Just ignored it?
For example, the following command:
gcc -E -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
and the resulting assembly file (tmp.result) is:
# 1 "arch/x86/boot/copy.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "arch/x86/boot/copy.S"
# 11 "arch/x86/boot/copy.S"
# 1 "include/linux/linkage.h" 1
# 1 "include/linux/compiler.h" 1
# 5 "include/linux/linkage.h" 2
# 1 "include/linux/stringify.h" 1
# 6 "include/linux/linkage.h" 2
# 1 "include/linux/export.h" 1
# 26 "include/linux/export.h"
struct kernel_symbol
{
unsigned long value;
const char *name;
};
# 7 "include/linux/linkage.h" 2
# 1 "arch/x86/include/asm/linkage.h" 1
# 8 "include/linux/linkage.h" 2
# 12 "arch/x86/boot/copy.S" 2
.code16
.text
GLOBAL(memcpy)
pushw %si
pushw %di
movw %ax, %di
movw %dx, %si
pushw %cx
shrw $2, %cx
rep; movsl
popw %cx
andw $3, %cx
rep; movsb
popw %di
popw %si
retl
ENDPROC(memcpy)
but when trying to assemble this file:
as -o tmp.o tmp.result
produce following error:
include/linux/export.h: Assembler messages:
include/linux/export.h:26: Error: no such instruction: `struct kernel_symbol'
include/linux/export.h:27: Error: junk at end of line, first unrecognized character is `{'
include/linux/export.h:28: Error: no such instruction: `unsigned long value'
include/linux/export.h:29: Error: no such instruction: `const char *name'
include/linux/export.h:30: Error: junk at end of line, first unrecognized character is `}'
arch/x86/boot/copy.S:20: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:34: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:36: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:49: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:51: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:58: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:60: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:67: Error: invalid character '(' in mnemonic
It seems that the assembler can not deal with the struct in tmp.result. How can Linux source code(.S) get through the assembling?
as cannot process struct and function prototypes - they are just for the C compiler, and get "pulled in" in your preprocessing by mistake. In facts, if you look at the header that provides that struct definition, you'll see:
#ifndef __ASSEMBLY__
struct kernel_symbol
{
unsigned long value;
const char *name;
};
So, the header above is thought to be included both from assembly and from C, but you didn't define __ASSEMBLY__ to tell it that you are including it into an assembly file.
Interestingly, gcc does have a builtin __ASSEMBLER__ predefined macro to discriminate between an inclusion in an assembly file or a C file, but it seems that the kernel does not use it for historical reasons, relying instead on defining manually __ASSEMBLY__ when preprocessing assembly files.
Long story short: to get the correct output from the preprocessor, you should be doing something like
gcc -E -D__ASSEMBLY__ -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
(disclaimer: I'm not entirely familiar with the kernel build process, the line above may have other problems with include paths, or maybe the correct way would be to invoke cpp instead of gcc or whatever - I don't know)

minimal typing command line calculator - tcsh vs bash

I like to have a command-line calculator handy. The requirements are:
Support all the basic arithmetic operators: +, -, /, *, ^ for exponentiation, plus parentheses for grouping.
Require minimal typing, I don't want to have to call a program interact with it then asking it to exit.
Ideally only one character and a space in addition to the expression itself should be entered into the command line.
It should know how to ignore commas and dollar (or other currency symbols)
in numbers to allow me to copy/paste from the web without worrying
about having to clean every number before pasting it into the calculator
Be white-space tolerant, presence or lack of spaces shouldn't cause errors
No need for quoting anything in the expression to protect it from the shell - again for the benefit of minimal typing
Since tcsh supports alias positional arguments, and since alias expansion precedes all other expansions except history-expansion, it was straight forward to implement something close to my ideal in tcsh.
I used this:
alias C 'echo '\''\!*'\'' |tr -d '\'',\042-\047'\'' |bc -l'
Now I can do stuff like the following with minimal typing:
# the basic stuff:
tcsh> C 1+2
3
# dollar signs, multiplication, exponentiation:
tcsh> C $8 * 1.07^10
15.73721085831652257992
# parentheses, mixed spacing, zero power:
tcsh> C ( 2+5 ) / 8 * 2^0
.87500000000000000000
# commas in numbers, no problem here either:
tcsh> C 1,250.21 * 1.5
1875.315
As you can see there's no need to quote anything to make all these work.
Now comes the problem. Trying to do the same in bash, where parameter aliases aren't supported forces me to implement the calculator as a shell function and pass the parameters using "$#"
function C () { echo "$#" | tr -d ', \042-\047' | bc -l; }
This breaks in various ways e.g:
# works:
bash$ C 1+2
3
# works:
bash$ C 1*2
2
# Spaces around '*' lead to file expansion with everything falling apart:
bash$ C 1 * 2
(standard_in) 1: syntax error
(standard_in) 1: illegal character: P
(standard_in) 1: illegal character: S
(standard_in) 1: syntax error
...
# Non-leading parentheses seem to work:
bash$ C 2*(2+1)
6
# but leading-parentheses don't:
bash$ C (2+1)*2
bash: syntax error near unexpected token `2+1'
Of course, adding quotes around the expression solves these issues, but is against the original requirements.
I understand why things break in bash. I'm not looking for explanations. Rather, I'm looking for a solution which doesn't require manually quoting the arguments. My question to bash wizards is is there any way to make bash support the handy minimal typing calculator alias. Not requiring quoting, like tcsh does? Is this impossible? Thanks!
If you're prepared to type C Enter instead of C Space, the sky's the limit. The C command can take input in whatever form you desire, unrelated to the shell syntax.
C () {
local line
read -p "Arithmetic: " -e line
echo "$line" | tr -d \"-\', | bc -l
}
In zsh:
function C {
local line=
vared -p "Arithmetic: " line
echo $line | tr -d \"-\', | bc -l
}
In zsh, you can turn off globbing for the arguments of a specific command with the noglob modifier. It is commonly hidden in an alias. This prevents *^() from begin interpreted literally, but not quotes or $.
quickie_arithmetic () {
echo "$*" | tr -d \"-\', | bc -l
}
alias C='noglob quickie_arithmetic'
At least preventing the expansion of * is possible using 'set -f' (following someone's blog post:
alias C='set -f -B; Cf '
function Cf () { echo "$#" | tr -d ', \042-\047' | bc -l; set +f; };
Turning it off in the alias, before the calculation, and back on afterwards
$ C 2 * 3
6
I downloaded the bash sources and looked very closely. It seems the parenthesis error occurs directly during the parsing of the command line, before any command is run or alias is expanded. And without any flag to turn it off.
So it would be impossible to do it from a bash script.
This means, it is time to bring the heavy weapons. Before parsing the command line is read from stdin using readline. Therefore, if we intercept the call to readline, we can do whatever we want with the command line.
Unfortunately bash is statically linked against readline, so the call cannot be intercepted directly. But at least readline is a global symbol, so we can get the address of the function using dlsym, and with that address we can insert arbitrary instructions in readline.
Modifying readline directly is prune to errors, if readline is changed between the different bash version, so we modify the function calling readline, leading to following plan:
Locate readline with dlsym
Replace readline with our own function that uses the current stack to locate the function calling readline (yy_readline_get) on its first call and then restores the original readline
Modify yy_readline_get to call our wrapper function
Within the wrapper function: Replace the parentheses with non problematic symbols, if the input starts with "C "
Written in C for amd64, we get:
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#ifndef __USE_GNU
#define __USE_GNU
#endif
#ifndef __USE_MISC
#define __USE_MISC
#endif
#include <dlfcn.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
//-----------Assembler helpers----------
#if (defined(x86_64) || defined(__x86_64__))
//assembler instructions to read rdp, which we need to read the stack
#define MOV_EBP_OUT "mov %%rbp, %0"
//size of a call instruction
#define RELATIVE_CALL_INSTRUCTION_SIZE 5
#define IS64BIT (1)
/*
To replace a function with a new one, we use the push-ret trick, pushing the destination address on the stack and let ret jump "back" to it
This has the advantage that we can set an additional return address in the same way, if the jump goes to a function
This struct corresponds to the following assembler fragment:
68 ???? push <low_dword (address)>
C7442404 ???? mov DWORD PTR [rsp+4], <high_dword (address) )
C3 ret
*/
typedef struct __attribute__((__packed__)) LongJump {
char push; unsigned int destinationLow;
unsigned int mov_dword_ptr_rsp4; unsigned int destinationHigh;
char ret;
// char nopFiller[16];
} LongJump;
void makeLongJump(void* destination, LongJump* res) {
res->push = 0x68;
res->destinationLow = (uintptr_t)destination & 0xFFFFFFFF;
res->mov_dword_ptr_rsp4 = 0x042444C7;
res->destinationHigh = ((uintptr_t)(destination) >> 32) & 0xFFFFFFFF;
res->ret = 0xC3;
}
//Macros to save and restore the rdi register, which is used to pass an address to readline (standard amd64 calling convention)
typedef unsigned long SavedParameter;
#define SAVE_PARAMETERS SavedParameter savedParameters; __asm__("mov %%rdi, %0": "=r"(savedParameters));
#define RESTORE_PARAMETERS __asm__("mov %0, %%rdi": : "r"(savedParameters));
#else
#error only implmented for amd64...
#endif
//Simulates the effect of the POP instructions, popping from a passed "stack pointer" and returning the popped value
static void * pop(void** stack){
void* temp = *(void**)(*stack);
*stack += sizeof(void*);
return temp;
}
//Disables the write protection of an address, so we can override it
static int unprotect(void * POINTER){
const int PAGESIZE = sysconf(_SC_PAGE_SIZE);;
if (mprotect((void*)(((uintptr_t)POINTER & ~(PAGESIZE-1))), PAGESIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) {
fprintf(stderr, "Failed to set permission on %p\n", POINTER);
return 1;
}
return 0;
}
//Debug stuff
static void fprintfhex(FILE* f, void * hash, int len) {
for (int i=0;i<len;i++) {
if ((uintptr_t)hash % 8 == 0 && (uintptr_t)i % 8 == 0 && i ) fprintf(f, " ");
fprintf(f, "%.2x", ((unsigned char*)(hash))[i]);
}
fprintf(f, "\n");
}
//---------------------------------------
//Address of the original readline function
static char* (*real_readline)(const char*)=0;
//The wrapper around readline we want to inject.
//It replaces () with [], if the command line starts with "C "
static char* readline_wrapper(const char* prompt){
if (!real_readline) return 0;
char* result = real_readline(prompt);
char* temp = result; while (*temp == ' ') temp++;
if (temp[0] == 'C' && temp[1] == ' ')
for (int len = strlen(temp), i=0;i<len;i++)
if (temp[i] == '(') temp[i] = '[';
else if (temp[i] == ')') temp[i] = ']';
return result;
}
//Backup of the changed readline part
static unsigned char oldreadline[2*sizeof(LongJump)] = {0x90};
//A wrapper around the readline wrapper, needed on amd64 (see below)
static LongJump* readline_wrapper_wrapper = 0;
static void readline_initwrapper(){
SAVE_PARAMETERS
if (readline_wrapper_wrapper) { fprintf(stderr, "ERROR!\n"); return; }
//restore readline
memcpy(real_readline, oldreadline, 2*sizeof(LongJump));
//find call in yy_readline_get
void * frame;
__asm__(MOV_EBP_OUT: "=r"(frame)); //current stackframe
pop(&frame); //pop current stackframe (??)
void * returnToFrame = frame;
if (pop(&frame) != real_readline) {
//now points to current return address
fprintf(stderr, "Got %p instead of %p=readline, when searching caller\n", frame, real_readline);
return;
}
void * caller = pop(&frame); //now points to the instruction following the call to readline
caller -= RELATIVE_CALL_INSTRUCTION_SIZE; //now points to the call instruction
//fprintf(stderr, "CALLER: %p\n", caller);
//caller should point to 0x00000000004229e1 <+145>: e8 4a e3 06 00 call 0x490d30 <readline>
if (*(unsigned char*)caller != 0xE8) { fprintf(stderr, "Expected CALL, got: "); fprintfhex(stderr, caller, 16); return; }
if (unprotect(caller)) return;
//We can now override caller to call an arbitrary function instead of readline.
//However, the CALL instruction accepts only a 32 parameter, so the called function has to be in the same 32-bit address space
//Solution: Allocate memory at an address close to that CALL instruction and put a long jump to our real function there
void * hint = caller;
readline_wrapper_wrapper = 0;
do {
if (readline_wrapper_wrapper) munmap(readline_wrapper_wrapper, 2*sizeof(LongJump));
readline_wrapper_wrapper = mmap(hint, 2*sizeof(LongJump), PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (readline_wrapper_wrapper == MAP_FAILED) { fprintf(stderr, "mmap failed: %i\n", errno); return; }
hint += 0x100000;
} while ( IS64BIT && ( (uintptr_t)readline_wrapper_wrapper >= 0xFFFFFFFF + ((uintptr_t) caller) ) ); //repeat until we get an address really close to caller
//fprintf(stderr, "X:%p\n", readline_wrapper_wrapper);
makeLongJump(readline_wrapper, readline_wrapper_wrapper); //Write the long jump in the newly allocated space
//fprintfhex(stderr, readline_wrapper_wrapper, 16);
//fprintfhex(stderr, caller, 16);
//patch caller to become call <readline_wrapper_wrapper>
//called address is relative to address of CALL instruction
*(uint32_t*)(caller+1) = (uint32_t) ((uintptr_t)readline_wrapper_wrapper - (uintptr_t)(caller + RELATIVE_CALL_INSTRUCTION_SIZE) );
//fprintfhex(stderr, caller, 16);
*(void**)(returnToFrame) = readline_wrapper_wrapper; //change stack to jump to wrapper instead real_readline (or it would not work on the first entered command)
RESTORE_PARAMETERS
}
static void _calc_init(void) __attribute__ ((constructor));
static void _calc_init(void){
if (!real_readline) {
//Find readline
real_readline = (char* (*)(const char*)) dlsym(RTLD_DEFAULT, "readline");
if (!real_readline) return;
//fprintf(stdout, "loaded %p\n", real_readline);
//fprintf(stdout, " => %x\n", * ((int*) real_readline));
if (unprotect(real_readline)) { fprintf(stderr, "Failed to unprotect readline\n"); return; }
memcpy(oldreadline, real_readline, 2*sizeof(LongJump)); //backup readline's instructions
//Replace readline with readline_initwrapper
makeLongJump(real_readline, (LongJump*)real_readline); //add a push/ret long jump from readline to readline, to have readline's address on the stack in readline_initwrapper
makeLongJump(readline_initwrapper, (LongJump*)((char*)real_readline + sizeof(LongJump) - 1)); //add a push/ret long jump from readline to readline_initwrapper, overriding the previous RET
}
}
This can be compiled to an intercepting library with:
gcc -g -std=c99 -shared -fPIC -o calc.so -ldl calc.c
and then loaded in bash with:
gdb --batch-silent -ex "attach $BASHPID" -ex 'print dlopen("calc.so", 0x101)'
Now, when the previous alias extended with parenthesis replacement is loaded:
alias C='set -f -B; Cf '
function Cf () { echo "$#" | tr -d ', \042-\047' | tr [ '(' | tr ] ')' | bc -l; set +f; };
We can write:
$ C 1 * 2
2
$ C 2*(2+1)
6
$ C (2+1)*2
6
Even better it becomes, if we switch from bc to qalculate:
alias C='set -f -B; Cf '
function Cf () { echo "$#" | tr -d ', \042-\047' | tr [ '(' | tr ] ')' | xargs qalc ; set +f; };
Then we can do:
$ C e ^ (i * pi)
e^(i * pi) = -1
$ C 3 c
3 * speed_of_light = approx. 899.37737(km / ms)

Temporarily disable gcc warning on redefinition

I'm trying to make this work (in GCC 4.6) without barking at me.
#define FOO ""
#define BAR ""
#if ....
#define FOO "Foo, good sir"
#endif
#if ...
#define BAR "Bar, my lady"
#endif
....
#define EVERYTHING FOO BAR ...
I am going to have a lot of these. So doing it that way instead of:
#if ...
#define FOO "Foo"
#else
#define FOO ""
#endif
Saves a lot of code, and makes it more readable. The warning that I get is:
warning: "FOO" redefined [enabled by default]
Is there a way to disable this warning in the code for this particular section? I found Diagnostic Pragmas to disable certain warnings, but I'm not able to find which warning (in this list of Options to Request or Suppress Warnings) that needs to be disabled here.
Anyone know how to do this? Or a different way to avoid having to #else #define all of them to the empty string?
Try using #undef:
#define FOO ""
#if ....
#undef FOO
#define FOO "Foo, good sir"
#endif
This warning comes from file named "cccp.c" in gcc (as of 2.95 version; is this file from "Soviet Russia"?), and it can't be turned off. There is still no option to disable this warning individually even in git head, gcc/libcpp/macro.c file (line 2527 and line 2994 of the same file)
I'll cite sources a bit.
2525 /* Returns nonzero if a macro redefinition warning is required. */
2526 static bool
2527 warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node,
2528 const cpp_macro *macro2)
2529 {
...
2537 /* Suppress warnings for builtins that lack the NODE_WARN flag. */
..
2545 /* Redefinitions of conditional (context-sensitive) macros, on
2546 the other hand, must be allowed silently. */
...
2550 /* Redefinition of a macro is allowed if and only if the old and new
2551 definitions are the same. (6.10.3 paragraph 2). */
...
2561 /* Check parameter spellings. */
...
2566 /* Check the replacement text or tokens. */
...
2573 for (i = 0; i < macro1->count; i++)
2574 if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
2575 return true;
So in your case warn_of_redefinition function will return true. And here is real usage:
2989 if (node->type == NT_MACRO)
2990 {
2991 if (CPP_OPTION (pfile, warn_unused_macros))
2992 _cpp_warn_if_unused_macro (pfile, node, NULL);
2993
2994 if (warn_of_redefinition (pfile, node, macro))
2995 {
2996 const int reason = (node->flags & NODE_BUILTIN)
2997 ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
2998 bool warned;
2999
3000 warned = cpp_pedwarning_with_line (pfile, reason,
3001 pfile->directive_line, 0,
3002 "\"%s\" redefined",
3003 NODE_NAME (node));
3004
3005 if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
3006 cpp_error_with_line (pfile, CPP_DL_NOTE,
3007 node->value.macro->line, 0,
3008 "this is the location of the previous definition");
3009 }
3010 }
So, there is no any specific option. And answer by Greg is good for this case, just undefine your empty string just before redefinition.
Or try using if else.
#if ...
# define FOO "Foo, doof sir"
#else
# define FOO ""
#endif

gcc inline assembler shift left problem

I'm having trouble compiling the code below. It may also have logical errors, please help. thanks,
#include <iostream>
using namespace std;
int main()
{
int shifted_value;
int value = 2;
__asm__("shll %%eax,%1;" : "=a" (shifted_value): "a" (value));
cout<<shifted_value<<endl;
return 0 ;
}
The error is:
Error: suffix or operands invalid for `shl'
It should look like
__asm__(("shll %%cl, %%eax;"
: "=a" (shifted_value)
: "a" (shifted_value), "c" (value)
);
Credit for correct code goes to the other answer for pointing out that the operands were in the incorrect order.
You dont need to specify eax as clobbered because eax is an output register.
it can work with shll also, shll being the GNU at&t mnemonic for "shift left longword". However, the invalid operand error is due to the operand needing to come first! I found this out when I googled up these sources: http://meplayer.googlecode.com/svn-history/r23/trunk/meplayer/src/filters/transform/mpcvideodec/ffmpeg/libavcodec/cabac.h. I also used the excellent http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s6
Here is one way that works, taking into account Jesus Ramos's observation that shifted_value needs to be initialized:
jcomeau#intrepid:/tmp$ cat test.cpp; make test; ./test
#include <iostream>
using namespace std;
int main()
{
int shifted_value = 1;
char value = 2;
__asm__("shll %%cl, %%eax;"
: "=a" (shifted_value)
: "a" (shifted_value), "c" (value)
);
cout<<shifted_value<<endl;
return 0 ;
}
g++ test.cpp -o test
4

Resources