July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tue, Jul 14, 2009 at 5:13 PM, Walter Bright<newshound1@digitalmars.com> wrote: > Rainer Deyke wrote: >> >> Walter Bright wrote: >>> >>> It's not about protecting idiots. It's about making the better way to do things the easier and more natural way, and making the worse more difficult. >> >> Making the better way easy is a worthwhile goal. Making the worse way more difficult is not. A programming language should never set out to intentionally make things difficult for the programmer. > > Why do C and C++ (and D) make it difficult to do: > > char *p; > p |= 1; > > ? There's no implementation difficulty in accepting such and generating correct code for it. It's purely a matter of making what is generally considered to be bad practice harder to do. I've never heard anyone argue that this was a bad decision. I've never ever needed to do that, or been the slightest bit tempted to. The operation doesn't make sense. So I think the analogy is inappropos. In contrast, using the negation of a version makes plenty of sense. As does versioning out an entry in an enum that doesn't apply for some reason. ---bb | |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote: > On Tue, Jul 14, 2009 at 5:13 PM, Walter > Bright<newshound1@digitalmars.com> wrote: >> Why do C and C++ (and D) make it difficult to do: >> >> char *p; >> p |= 1; >> >> ? There's no implementation difficulty in accepting such and generating >> correct code for it. It's purely a matter of making what is generally >> considered to be bad practice harder to do. I've never heard anyone argue >> that this was a bad decision. > > I've never ever needed to do that, or been the slightest bit tempted > to. The operation doesn't make sense. So I think the analogy is > inappropos. I beg to differ. My C++ compiler implementation of precompiled headers uses bit 0 to determine if a pointer needs to be adjusted based on where it is loaded into memory or not. Using the bottom two bits as flags (because the pointers were aligned) is not all that uncommon. I've seen it done by major companies on some major, very successful projects. Then there's the famous pointer "xor hack". > In contrast, using the negation of a version makes plenty > of sense. As you wrote, we've hashed through that before. Over time, I've eliminated nearly all the negated conditionals from my code, and have been happier with the results. Half of them turned out to be bogus anyway, because I'd add a 3rd state and then latent undetected bugs would appear. Here's one of my faves: #ifndef _WIN32 ... do something for Linux ... #endif Does this happen in reality? I grepped #ifndef's from the Hans Boehm gc: version.h:#ifndef GC_NO_VERSION_VAR allchblk.c:#ifndef USE_MUNMAP alloc.c:#ifndef SMALL_CONFIG AmigaOS.c:#ifndef GC_AMIGA_FASTALLOC AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST AmigaOS.c:#ifndef GC_AMIGA_FASTALLOC AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST dbg_mlc.c:#ifndef SHORT_DBG_HDRS dbg_mlc.c:#ifndef SHORT_DBG_HDRS dbg_mlc.c:#ifndef SHORT_DBG_HDRS dbg_mlc.c:#ifndef SHORT_DBG_HDRS dyn_load.c:#ifndef _sigargs finalize.c:#ifndef NO_DEBUGGING finalize.c:#ifndef JAVA_FINALIZATION_NOT_NEEDED irix_threads.c:#ifndef LINT linux_threads.c:#ifndef __GNUC__ linux_threads.c:#ifndef SIG_THR_RESTART mach_dep.c:#ifndef USE_GENERIC_PUSH_REGS mach_dep.c:#ifndef SPARC mark.c:#ifndef THREADS mark.c:#ifndef UNALIGNED mark.c:#ifndef SMALL_CONFIG mark.c:#ifndef SMALL_CONFIG misc.c:#ifndef _WIN32_WCE misc.c:#ifndef PCR new_hblk.c:#ifndef SMALL_CONFIG os_dep.c:#ifndef HEAP_START os_dep.c:#ifndef THREADS solaris_pthreads.c:#ifndef LINT solaris_threads.c:#ifndef MMAP_STACKS solaris_threads.c:#ifndef LINT The #ifndef NO_DEBUGGING is awful. The #ifndef __GNUC__ means compile for every unknown compiler ever, except gcc. Can't possibly be right. Let's try grepping for !defined. We get: allchblk.c:# if !defined(NO_DEBUGGING) alloc.c:# if !defined(MACOS) && !defined(MSWINCE) alloc.c:# if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) alloc.c:# if !defined(NO_DEBUGGING) alloc.c:# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) AmigaOS.c:#if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM) checksums.c:# if !defined(MSWIN32) && !defined(MSWINCE) dyn_load.c:#if !defined(MACOS) && !defined(_WIN32_WCE) dyn_load.c: && !defined(GC_USE_LD_WRAP) dyn_load.c: && !defined(PCR) dyn_load.c:#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \ dyn_load.c: !defined(MSWIN32) && !defined(MSWINCE) && \ dyn_load.c: !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ dyn_load.c: !defined(RS6000) && !defined(SCO_ELF) && \ dyn_load.c:#if defined(SUNOS5DL) && !defined(USE_PROC_FOR_LIBRARIES) dyn_load.c:#if defined(SUNOS4) && !defined(USE_PROC_FOR_LIBRARIES) dyn_load.c:# if !defined(PCR) && !defined(SOLARIS_THREADS) && defined(THREADS) dyn_load.c:# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32 dyn_load.c:#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX)) dyn_load.c:# if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION) finalize.c:# if !defined(THREADS) && !defined(DBG_HDRS_ALL) gc_dlopen.c:# if defined(dlopen) && !defined(GC_USE_LD_WRAP) linux_threads.c:# if defined(HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \ linux_threads.c: && !defined(USE_HPUX_TLS) linux_threads.c:# if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_HPUX_TLS) linux_threads.c:# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) linux_threads.c:# if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ linux_threads.c: || !defined(__GNUC__) linux_threads.c:#if !defined(HPUX_THREADS) && !defined(GC_OSF1_THREADS) linux_threads.c:# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) linux_threads.c:# if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ linux_threads.c: && !defined(USE_HPUX_TLS) && !defined(DBG_HDRS_ALL) linux_threads.c:# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) linux_threads.c:#if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK) mach_dep.c:#if defined(__MWERKS__) && !defined(POWERPC) mach_dep.c:# if defined(I386) &&!defined(OS2) &&!defined(SVR4) \ mach_dep.c: && (defined(__MINGW32__) || !defined(MSWIN32)) \ mach_dep.c: && !defined(SCO) && !defined(SCO_ELF) \ mach_dep.c: && !defined(DOS4GW) mach_dep.c:# if defined(I386) && defined(MSWIN32) && !defined(__MINGW32__) \ mach_dep.c: && !defined(USE_GENERIC) mach_dep.c:# if !defined(POWERPC) && !defined(UTS4) mach_dep.c:# if !defined(PJ) && !(defined(MIPS) && defined(LINUX)) mach_dep.c:#if defined(ASM_CLEAR_CODE) && !defined(THREADS) MacOS.c:# if !defined(SHARED_LIBRARY_BUILD) MacOS.c:# if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD) mallocx.c:#if defined(THREADS) && !defined(SRC_M3) mark.c:# if !defined(IA64) && !defined(HP_PA) mark.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) mark.c:# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) mark.c:# if !defined(SMALL_CONFIG) && !defined(UNALIGNED) && \ mark.c: !defined(USE_MARK_BYTES) mark_rts.c: # if !defined(MSWIN32) && !defined(MSWINCE) mark_rts.c:# if !defined(NO_DEBUGGING) mark_rts.c:#if !defined(MSWIN32) && !defined(MSWINCE) mark_rts.c:# if !defined(MSWIN32) && !defined(MSWINCE) mark_rts.c:# if !defined(MSWIN32) && !defined(MSWINCE) mark_rts.c:# if !defined(MSWIN32) && !defined(MSWINCE) mark_rts.c: || defined(PCR)) && !defined(SRC_M3) mark_rts.c:# if !defined(USE_GENERIC_PUSH_REGS) misc.c: || defined(LINUX_THREADS) && !defined(USE_SPIN_LOCK) misc.c:# if !defined(THREADS) && defined(GC_ASSERTIONS) misc.c:# if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \ misc.c:# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN) misc.c:# if !defined(_AUX_SOURCE) || defined(__GNUC__) misc.c:# if !defined(SMALL_CONFIG) misc.c:#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) misc.c:# if !defined(AMIGA) misc.c:#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) && !defined(MACOS) misc.c:#if defined(LINUX) && !defined(SMALL_CONFIG) misc.c:#if !defined(NO_DEBUGGING) os_dep.c:# if defined(LINUX) && !defined(POWERPC) os_dep.c:# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \ os_dep.c: && !defined(MSWINCE) os_dep.c:# if !defined(MSWIN32) && !defined(SUNOS4) os_dep.c:# if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2) os_dep.c:# if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR) os_dep.c:# if (defined(SVR4) || defined(AUX) || defined(DGUX)) && !defined(PCR) os_dep.c:#if !defined(NO_EXECUTE_PERMISSION) os_dep.c:# if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */ os_dep.c:# if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \ os_dep.c: && !defined(MSWINCE) \ os_dep.c: && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) os_dep.c:# if defined(sigmask) && !defined(UTS4) os_dep.c:#if defined(PRINTSTATS) && !defined(THREADS) os_dep.c:#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \ os_dep.c: && !defined(MSWINCE) && !defined(OS2) os_dep.c: || (defined(LINUX) && defined(SPARC))) && !defined(PCR) os_dep.c:# if !defined(PCR) && !defined(SRC_M3) && !defined(NEXT) && !defined(MACOS) \ os_dep.c: && !defined(MACOSX) os_dep.c:# if !defined(PCR) && (defined(NEXT) || defined(MACOSX)) os_dep.c:# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \ os_dep.c: && !defined(MSWIN32) && !defined(MSWINCE) \ os_dep.c: && !defined(MACOS) && !defined(DOS4GW) os_dep.c:# if !defined(LINUX) os_dep.c:#if !defined(MSWIN32) && !defined(MSWINCE) os_dep.c:# if !defined(MSWIN32) && !defined(MSWINCE) os_dep.c:# if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA) || defined(IA64) os_dep.c:# if !defined(MSWIN32) && !defined(MSWINCE) os_dep.c:#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(LINUX_THREADS) \ os_dep.c: && !defined(GC_USE_LD_WRAP) os_dep.c:# if defined(__STDC__) && !defined(SUNOS4) os_dep.c: (!defined(SMALL_CONFIG) || defined(USE_PROC_FOR_LIBRARIES)) os_dep.c:#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) ptr_chck.c: && !defined(SRC_M3) reclaim.c:#if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES) reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) reclaim.c:# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) reclaim.c:# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) reclaim.c:#if !defined(NO_DEBUGGING) stlport is not quite as bad: src\c_locale_win32\c_locale_win32.c:#if !defined (LC_MAX) stlport\stl\_algo.c:# if !defined (_STLP_INTERNAL_ALGO_H) stlport\stl\_algobase.c:# if !defined (_STLP_INTERNAL_ALGOBASE_H) stlport\stl\_limits.c:# if !defined (_STLP_LIMITS_C) stlport\stl\_list.c:#if !defined (__WATCOMC__) stlport\stl\_num_get.c:# if defined(_STLP_LONG_LONG)&&!defined(__MRC__) //*ty 12/07/2001 - MrCpp can not cast from long long to void* stlport\stl\_num_put.c:# if defined(_STLP_LONG_LONG) && !defined(__MRC__) //*ty 11/24/2001 - MrCpp can not cast from void* to long long stlport\stl\_ostream.c:#if !defined (_STLP_INTERNAL_NUM_PUT_H) stlport\stl\_rope.c:#if !defined (_STLP_USE_NO_IOSTREAMS) stlport\stl\_rope.c:#if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable stlport\stl\_rope.c:# if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable stlport\stl\_rope.c:# if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable stlport\stl\_rope.c:# if !defined (_STLP_NO_METHOD_SPECIALIZATION) stlport\stl\_rope.c:#endif /* if !defined (_STLP_USE_NO_IOSTREAMS) */ stlport\stl\_rope.c:#if !defined (_STLP_USE_NO_IOSTREAMS) stlport\stl\_rope.c:# if !defined(__GC) && defined(_STLP_USE_EXCEPTIONS) stlport\stl\_streambuf.c:# if !defined (_STLP_NO_WCHAR_T) stlport\stl\_string.c:# if defined (_STLP_USE_OWN_NAMESPACE) || !defined (_STLP_USE_NATIVE_STRING) stlport\stl\_string.c:# if !defined (_STLP_LINK_TIME_INSTANTIATION) stlport\stl\_string_fwd.c:#if !defined ( _STLP_STRING_FWD_C) && ! defined (_STLP_OWN_IOSTREAMS) stlport\stl\_threads.c:# if !defined ( _STLP_ATOMIC_EXCHANGE ) && (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS)) stlport\stl\_vector.c:# if !defined (_STLP_INTERNAL_VECTOR_H) stlport\stl\debug\_debug.c:# if !defined( _STLP_DEBUG_MESSAGE ) src\c_locale_win32\c_locale_win32.c:#ifndef _LEADBYTE See all those !(NO_FEATURE) constructs? Not no-how, not no-way! And people say my use of goto is bad and should be taken away from me :-) I tried it on the Microsoft Windows api headers. Many pages of very dubious use follow, no need to post it all here. This stuff is marquee showcase code by professional well-paid corporate developers, not idiots or newbies. I slip into writing such crud, too. > As does versioning out an entry in an enum that doesn't > apply for some reason. Can we discuss a real example of this? I think perhaps we can find a way to accommodate the desired result (if not the method) in a clean manner. | |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright:
> Using the bottom two bits as flags (because the pointers were aligned) is not all that uncommon. I've seen it done by major companies on some major, very successful projects.
That's done often enough, one or two bits in tagged pointers are useful to implement various data structures (and they are used by garbage collectors too). I even used tagged pointers once in D, using memory allocated from the C heap.
Bye,
bearophile
| |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright schrieb:
> Don wrote:
>> In this case you may have a long function, with only a single instruction right in the middle which needs to be changed.
>
> void foo()
> {
> asm
> {
> mov EAX,EAX;
> ... lots more instructions ...
> }
> version (bar) asm
> {
> mov EAX,EAX;
> }
> asm
> {
> ... even more instructions ...
> mov EAX,EAX;
> }
> }
Man, it's so obvious, yet I wouldn't have hit on that ;)
| |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Trass3r | Trass3r wrote:
> Man, it's so obvious, yet I wouldn't have hit on that ;)
Most obvious things are obvious only in hindsight <g>.
| |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright, el 14 de julio a las 14:52 me escribiste: > Leandro Lucarella wrote: > >The same goes for version (!X) ..., I think it should be available, there > >are cases when the use is valid and you have to do artificial hacks like > >version (X) else .... It's like Java not having functions or global > >variable. You're just annoying people that know what they're doing to > >"protect" the idiots (which can go and use static methods and variables > >anyways; or version (X) else ...). > > It's not about protecting idiots. It's about making the better way to do things the easier and more natural way, and making the worse more difficult. > > In C++, > > int a[5]; > > is the wrong way, and: > > std::vector<int>(5) a; > > is the right way. C++ makes the right way ugly and hard. I'd like to reverse that. > > All languages have some characteristics of "you shouldn't be allowed to do that", the problem is where the line is drawn. > > I have long, long experience with #ifdef's. I know how convenient it is to just plop those things in, like your first hit of heroin. I know how justifiable just that one little old #ifdef is. Then you add in another, and another, and another, and another, and eventually wonder how you wound up with such an impenetrable thicket of awfulness. My own code gets like that (despite my knowing better) and just about every long lived piece of C/C++/asm code I've run across. I think you can always use it right when you have only one "#ifdef", and when you see that it's getting messy, you can refactor your code to go the way of "module personalities". If you can do that, the language can scale up *and* down. Otherwise the language is only suitable for big systems. Again, compare it to Java: for big systems is usually a good thing to use an architecture with several layers and OO with very "hard" interfaces. In Java you can only use that, you can't hack a quick script because it doesn't scale down. I think D should handle both worlds gracefully. > I do the same as you, running the preprocessor independently on C code to figure out what's happening. That, however, would be problematic with D as it doesn't have a preprocessor. You'd have to build a separate tool to do it. Again, people can make bad code in D anyways, you just make it a little harder, at the expense of making a little harder to use version more flexibly when it's right to do so (as Java make it harder to make a free function or a global variable). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Wenn ist das nunstück git und slotermeyer? Ja! Beiherhund das oder die Flipperwaldt gersput! -- Monty Python (no leer si sabés alemán) | |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote:
> Don wrote:
>> In this case you may have a long function, with only a single instruction right in the middle which needs to be changed.
>
> void foo()
> {
> asm
> {
> mov EAX,EAX;
> ... lots more instructions ...
> }
> version (bar) asm
> {
> mov EAX,EAX;
> }
> asm
> {
> ... even more instructions ...
> mov EAX,EAX;
> }
> }
Yes, of course, that is what I do. It's ugly, though, especially since you want to _remove_ code for version(bar).
asm {
...
}
version(D_PIC) {} else asm {
...
}
asm {
...
}
| |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Bill Baxter wrote: >> On Tue, Jul 14, 2009 at 5:13 PM, Walter >> Bright<newshound1@digitalmars.com> wrote: >>> Why do C and C++ (and D) make it difficult to do: >>> >>> char *p; >>> p |= 1; >>> >>> ? There's no implementation difficulty in accepting such and generating >>> correct code for it. It's purely a matter of making what is generally >>> considered to be bad practice harder to do. I've never heard anyone argue >>> that this was a bad decision. >> >> I've never ever needed to do that, or been the slightest bit tempted >> to. The operation doesn't make sense. So I think the analogy is >> inappropos. Often I wanted to write p &= ~3 in low level code. And that does make sense, because it aligns the pointer. > The #ifndef NO_DEBUGGING is awful. The #ifndef __GNUC__ means compile for every unknown compiler ever, except gcc. Can't possibly be right. The #ifndef NO_DEBUGGING causes the code to be compiled in debugging mode, if it isn't explicitly deactivated. This is a good thing. I think dmd should compile in debug mode too, and force the user to pass -nodebug to disable it. The #ifndef _GNUC_ is probably for using gcc compiler/libc extensions, which makes sense. | |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to grauzone | grauzone wrote:
> The #ifndef NO_DEBUGGING causes the code to be compiled in debugging mode, if it isn't explicitly deactivated.
"You, sir, are employing a double negative." -- Mr. Spock
It's not that it's impossible to figure out, it's that it's execrable style. In my experience, such constructs correlate strongly with incoherent and buggy code in the sections it appears in, including when I've used it.
The interesting question is is the construct itself the cause or the effect of incoherence and bugginess?
I'm asking you to give it a chance. Grep your own code for such. See if it could be redone without negation, and see if you like that better.
Even so, you *can* use negation in D version statements:
version (NO_DEBUGGING) {} else
{
... debugging is on ...
}
they're just a few more characters than laying down a single ! or n. Hopefully, they're enough extra effort that one will minimize the use of them.
| |||
July 15, 2009 Re: Conditional compilation inside asm and enum declarations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Wed, Jul 15, 2009 at 2:18 AM, Walter Bright<newshound1@digitalmars.com> wrote: > Don wrote: >> >> In this case you may have a long function, with only a single instruction right in the middle which needs to be changed. > > void foo() > { > asm > { > mov EAX,EAX; > ... lots more instructions ... > } > version (bar) asm > { > mov EAX,EAX; > } > asm > { > ... even more instructions ... > mov EAX,EAX; > } > } > Since when does D guarantee that no code is inserted before/after asm blocks? | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply