Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Josh @ Dreamland

Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 »
Announcements / Quick Poll
« on: March 08, 2010, 08:58:12 am »
As the more conscious of you realize by now, ENIGMA allows for C++-style declarations to be used in your projects. As you all should know, GM is very loose about its semicolons.

I asked Ism to create a script-like resource that will allow users to define their own structures and functions for use in the rest of the project. However, it is also legal in C to define structs in your code, and I don't want to alienate that as a feature.

For those who are new to C, structs are a simple data structure that lays out how chunks of memory look. They allow you to keep track of multiple things, like a named array. Instead of having, for example, a 2-Dimensional array to store x-y pairs, you could create a structure like the one featured below.

Veterans know that R3 allowed for cpp {} to handle such things. The cpp statement created a block of un-parsed code to allow users access to C++ without the parser having to check it for error, creating a workaround as well as a decent expandability. That block is no longer necessary for its old purpose; now we can choose to have it serve a new one along with it.

Say that in a create event, you want to create a structure with an X and Y pair. I don't know why you'd want to do this since you may as well just keep two arrays, but for the sake of example pretend you do.

Being used to the GM way, you say this:

Code: [Select]
struct xy {
  var x;
  var y;
direction = 0
speed = 0

That's a problem.
The parser would naively make your code look like this:
Code: [Select]
struct xy {
  var x;
  var y;
direction = 0;
speed = 0;

The above code looks correct, but in actuality, it redeclares direction as an xy structure in that piece of code. This is because the proper form for structure declaration in C is this:
Code: [Select]
struct name { int members; } instance; I'm sure you can all imagine why that isn't good... For those who can't, it means that for the rest of that code, the word "direction" will NOT refer to the builtin variable direction. It will instead refer to an instance of your xy structure, which behaves like an instance in GML. You could say direction.x = 0; direction.y = 1;, and it would be valid. To fix this, preventing the instantiation of immediate varnames (in this case, direction), you would simply add a semicolon following the closing brace.

Code: [Select]
struct xy {
  var x;
  var y;
direction = 0;
speed = 0;
The above piece behaves as one would expect.

All this considered, we are left with three options.
  • We can leave it up to the user to remember that semicolon.
     I still forget that semicolon at times. It is one of the most common mistakes in C/C++.
     It won't error, because direction is declared elsewhere. You'll have to figure it out yourself.
  • We can disallow immediate instantiation.
     This means that code will be treated as if the {} had been followed by a semicolon immediately, and that you cannot declare a new structure and instantiate it with one semicolon.
  • We can use cpp %{ %} for such declarations, erroring if the struct isn't in one.
     This is like the first option, but it will remind users to watch what they're doing. It's also pretty inconvenient, in my opinion. Whenever you want a new structure, you will have to input code similar to that below. I did like this suggestion when Miky made it, but then I couldn't make up my mind.

Code as entered for option 3:
Code: [Select]
cpp %{
  struct a {
    int b;
  } c;
Creates a structure called a, with a member called b, and instantiates it in a variable called c. You can say c.b = 0, for example.

Please read over carefully and make your choice; feel free to ask questions or justify your answer. You can change your vote (assuming SMF works like the checkbox implies it will), so don't be afraid to just place one.

Note that the script-like resource mentioned is pure C++, and so expects perfect grammar. This does not apply to it.

I also ask that you don't just randomly pick one, though picking one because your retarded friend told you to do so is fine. I figure cheating on polls is a good thing; it reflects who cares most.

Announcements / Prophase
« on: March 06, 2010, 12:47:05 am »
The C Parser is now hooked up such that it is self sufficient in collecting information.

On initialization, it asks the GCC to dump built-in #defines into a file that it can read. It parses those to gain the ability to correctly evaluate later preprocessors and the like, then it begins parsing SHELLmain.cpp, which will soon be moved (for the most part) to a separate header, since that particular source file shouldn't be responsible for all of that.

While getting it to work, I was met only with the problem of setting the working directory, which is currently temporarily resolved: I set it manually with a relative path that will have to be changed for the release compile.

However, once that was implemented, it made it through the entire project without incident. I asked it to print the contents of the enigma namespace to be sure it got it all, and was blown away.

At that, mission accomplished. I will make sure the GML parser and syntax checker are performing adequately tomorrow, which they shouldn't be, considering I am recoding a chunk of each to use the new input.

Expect material to be tested this coming week (Surprise). Don't expect anything grandiose during testing; I've not even hooked up the DLL functions yet. What you should see is vastly improved compile time and some small bugfixes that were made before the split. Serp's optimized code as well as the things that have been implemented since R3 are not part of the equation at this point.

In fact, the struggle of the next several days is going to be getting LGM to communicate better with ENIGMA, which has officially outgrown its separate-module form. I remember when syntax check rang in at 13x faster than GM's while code was being sent as a file. XD Those days are over, and now we'll be faster with dignity.

*commits code in whatever state it may be*

I haven't seen Ism today. I'll definitely need her for this part...
Ed suggests we use JNA to handle the interface as a DLL. We'll see how that works for us.

Ciao for now.

Announcements / Pride
« on: March 02, 2010, 11:21:36 pm »
I'm so proud of this little community for not hanging on security considerations when looking to the efficiency ones. :3

Good news. Here's the result of parsing this code:

Code: [Select]
#include <map>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <list>
#include <set>
#include <iostream>

#include <windows.h>

No error.
Parse time: 1509 milliseconds

Macros (12684) [+ ]
Variables [+ ]
Define: CreateWindow
  #define CreateWindow CreateWindowA
Define: CreateWindowA
  #define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k) CreateWindowExA(0,a,b,c,d,e,f,g,h,i,j,k)
Define: CreateWindowExA
  CreateWindowExA:  Function with 12 parameters, returning HWND__  Dereference path: (params = 786444)*</group>

Since Windows includes everything, and I do mean everything, that anyone could ever need to make a game, there's really no point in assuming the parser needs further work. The parser no longer requires lists of functions and types.

Oh, and, if you noticed the odd parameter count when I asked it to define CWExA, don't worry, it stores that count in a jumbled short. It used to dissect the short and display the actual parameter bounds, but the code that does so got lost in one SVN commit or another.

Since you've all proven to be concerned with efficiency, here are some related tidbits of considerations:

1) The most pressing efficiency loss when treating EDL more like GML than C relates to the switch () statement. Those of you who are particularly well-informed with either GM or ENIGMA know that both engines treat a switch like a less-ugly chain of if()s. The complexity is the same; an == check for each label. A consideration, however, is to make a small, close-to-perfect hash function. Basically, this will allow for var case labels using some template magic. GM People: Stop reading after this next sentence.

I believe this can be done in O(1), maybe with two or three checks a number. Basically, a hash function will be used on the input to each case label, assuming these are constant. (Thanks to the C parser, checking can be done on this when they are not literals [such as 3.14 or "some string"]. How great is that?) Basically, the hash will take the sum of first and last byte of any strings along with its length, do some round() tricks on floats, and leave ints alone (C++ doesn't allow switching anything but int, and doesn't allow case labels of anything but constant int). Now, the thought of course is, what if two strings produce the same hash? That's why one check is done at the case label. You'll see the same idea being employed in hash maps. I owe it to Luda that I was enlightened to it. If anyone has a better idea, of course, by all means...

2) The next most annoying thing is compatibility garbage related to simple functions, like draw_primitive_begin(). From my reckonings, GM uses DirectX's idea of a Vertex Buffer Object. That's not always an option for GL... R3 and lower use glBegin(). This raises a compatibility issue when drawing two at once (this is allowed in GML, but not in GL). The reason I assume GM uses VBO is that it can in fact keep two separate primitives going at once. Long, long ago I decided to deal with the problem by allowing a statically allocated array to be used to hold the points for quick iteration... I made it static because I didn't want the overhead each function call to make sure we hadn't overflown anything and needed more space. However, this meant either an annoying amount of memory overhead, or an equally or more annoying setting to allow the maximum number of points to be set. (I thought 360 would be reasonable for most applications, but...) Anyway, in retrospect, it was an awful idea (good thing it was #if'd out by default). I think the plan should be to try for VBO, but if it doesn't exist, just offer glBegin(), no buffering. (This would break some compatibility for people with Intel cards barely meeting stone-age GL specifications). The good news is, no one who had any decent coding practice would notice the break.

I figured I'd get your opinions on those little things as well. If/when there is a DirectX port, that won't really be a concern (the nice thing is that with DirectX, we can make the same decisions as Yoyo did, good or bad, and no one can complain. Too bad I'm still using GL).

I'd throw in a third thing, but that's probably enough to swallow for one post. Those who would like to put their two cents in on security issues can do so in the previous thread. I guess we'll just keep doing this until I have a public opinion on the decisions that haunted me in early development stages (I want to get it all right this time. Or at least most of it).

While you people decide that, I'll be replacing lists of types and functions in the GML formatter with the new lookup calls. (Also, I think I need to make sure "using namespace" works in the global scope. )

Announcements / Encryption
« on: March 02, 2010, 09:04:44 am »
Despite what I'd like to believe (and maybe even what I'd like you to believe), making something in C++ doesn't mean it can't have its resources modified or even stolen. ENIGMA (being C++) makes sure that code isn't such a resource. No one can decompile your game. However, we do have a problem.

Because ENIGMA will be a regular system, unoptimized output executables will have the same basic format. Furthermore, because it is open source, an encryption algorithm is even more futile than it was in Game Maker. I can't just hide a seed and expect everyone to give up before finding it.

Now, in R3, rooms were stored as an array in the source code. This means that it would take a good amount of skill to modify them, but it's still feasible. Someone with a decent knowledge of how GCC handles such could probably make a tool to do it. If ENIGMA were to inherit GM's better disassemblers, we could possibly face problems with such (the hope is that since no one can get all of it, no one will write a tool to get some of it).

Fortunately, as long as you let GCC optimize your code, it should be too irregular to be removable by an automated tool. (Even if it was removed, it couldn't be decompiled other than manually, don't worry.) However, I'm not sure about unoptimized code. It would be far too much work to decompile it back to EDL (especially with the C++ goodness that gets thrown in), but it may be possible to remove entire events and replace them (making games easy to mod or cheat).

What's more, unified sprite and sound encryption is worthless. Pidgin doesn't encrypt passwords it stores for users because the developers understand that in an open source project--and for that matter, in any other project--doing so accomplishes nothing. So ENIGMA can not have a unified encryption system to protect non-code resources.

Personally I don't see this as a problem. However, I know one of the reasons people are in awe of the idea of C++ is that they think it will protect such resources. I can't think of a decent game whose resources aren't an open book (there are many Windows resource extractors. Not to mention, you Valve fans, think Garry's Mod). But, I can think of a way to fix this.

R4, as some of you are aware, will allow you to define C++ functions for use in your game. This is a great way to do with DLLs (but do note that external_define has been done for months). I could allow the implementation of a function called resource_encrypt (and one called resource_decrypt) to allow users to define their own algorithms. This would be done with the hopes that such an algorithm would not be in a uniform position in the executable every time. :eng99: If it was, it'd be as simple as writing a tool to look for like bits of code and extract the new stuff. Though they could still not decompile your code (and I am talking about the algorithm), they could call the decryption algorithm themselves, right where it sits, on whatever resources they extracted. Frankly, I think our better bet is to not waste time on encryption.

To protect room tampering, ENIGMA could hard code their creations in a large function (which would be optimized hopefully to un-uniform gobbledy... but it could still be replaced by a determined expert).

The function could be implemented conditionally; only executing if it has been defined by the user. This is just an idea I'm putting out, thoughts welcome. Especially from assembly people.

TL;DR: Paranoia resulting from the idea of really talented people wasting their time hacking games. Mods are inevitable, resource extraction is hard to stop, decompilation highly unlikely (as in, no one will waste their time on a huge game, and automation is impossible).

Announcements / Rejoice
« on: February 18, 2010, 11:33:14 pm »
Everything I wanted to work at this juncture works now. It's almost bittersweet; the teeth-grating hard part is seemingly over.
There is a problem, though. Typical student-made C lexers take upwards of minutes to parse the STL headers. I figured since I didn't need much of the data a compiler needs, I could do a lexless run-over to gather desired information, thus saving oodles of time. Well, it worked, but not well enough. On average processor load on my pretty average computer, parsing all the STL headers takes between one and two seconds. The latest result being 1.53662. Honestly, it's nothing to cry about, but this means I shouldn't just parse this stuff each compile, meaning Ism and I have to work something out to have LGM load ENIGMA as a DLL. This way, it will be able to retain such information.

I had typed up a report of what comes next on the school computers, but those have lately been failing to post here. I guess I'll summarize:

- As soon as I have access to a Windows box, I will reparse the STL headers on it, and then test windows.h to make sure it works (I have no doubt that it will). I also need to test the GL headers.
- Development will need to be carried out on said Windows device for a few cycles. This is because I assume said device (the one I have picked out) is 64 bit. Serprex had some problems with 64 bit machines in the past; I need to be sure they do not persist.
- Speaking of serp, I need his version of the system. He has been optimizing it for a while now. This will probably all be done inside tomorrow.
- Since the development of ENIGMA's parser, a new GM format has been released, along with a new EGM File format. ENIGMA needs to be versed in this new format. The parser also needs updated to use the CFile parser's list instead of the small list of built-ins I used to keep. This is a large step on the road to full extensibility.

And speaking of extensibility, with it come implications. Logically, I can't optimize for run speed, compile time, and output size all at once. So, here's what seems to be destined:
  • When testing your game, it will compile quite fast. The output size will be tremendous (approaching the size of GM output as the project grows). Speed will be "decent," which is great by GM standard. Error handling will be as follows, as debated long ago:
    • In regular run mode and release mode, errors will either kill you or they won't. They are not likely to be checked for.
    • In debug mode, thorough checking will be done that could cause slowdown
    • The jury is out on build mode.
  • When compiling your game for final release, the process will take from 10 seconds to a minute. This depends not so much on your computer as on your optimization settings. C++ comes with a set of native-related optimizations, ENIGMA's most notable optimizations are to be as follows:
    • Unused functions will not be included. This is possible thanks entirely to the CFile parser. [size optimization]
    • Unused local variables can be removed. [memory optimization] [possibly {semi-}manual]
    • Switch statements will be replaced with a type of hash map where possible. This will be another feat of mostly the C parser. [speed optimization]

Other optimizations become difficult to describe and list due to number and insignificance (they only add up in the long run). Not to mention I'm really tired.

Before I go though, I should elaborate on the implications of having removable systems.
Each of ENIGMA's systems is designed now to be optional. Since R3, when compile time was too high, these groups of related functions have been divided into individual source files. The problem with doing so is that many files in ENIGMA are highly interdependent. Many sources need a few members from instances, most often id, sprite_index, and mask_index. To give access to these variables without requiring all variables, R4 will require a super-parent, if you will, that contains only the most basic of locals. Other locals, like speed and direction, will be stored in a derived parent from which all other objects will derive. This will allow for all non-essential locals to be removed without major recompile.

*yawns* I need sleep today.

Announcements / Domain Name Provider Transfer
« on: February 10, 2010, 07:02:10 am »
We'll be changing to a cheaper service. This may cause downtime lasting a span anywhere between now and this Sunday. Although this should not happen, it is a possibility, but don't worry, it'll be over soon.

Furthermore, progress.

String and Map both parse 100% correctly, but stack is another story. I will try to wrap it up, and if I fail, I'll simply move on.

EDIT: Okay, stack works. It was a simple missing check that I should have remembered to put there in the first place.

Announcements / Illogical
« on: February 04, 2010, 11:05:36 pm »
It doesn't make sense to me that line 405 of stl_algobase declares istreambuf_iterator like so:
Code: [Select]
  template<typename _CharT, typename _Traits>
    class istreambuf_iterator;
But then the class is later accessed like so:
Code: [Select]
typename _InIter = istreambuf_iterator<_CharT> >
On the bright side, however, the parser is old enough to read map with some success.
map:  Template [4]<typename _Key,typename _Tp,typename _Compare=less,typename _Alloc=allocator>  Serves as typename : struct

This means the parser is sane enough that I can probably continue FOR THE TIME BEING, but eventually must revisit the parser to get it working with foreign code for the sake of future extensibility. If ENIGMA is to escape the encroaching mediocrity that follows GM like a shadow, it will need such potency.

Furthermore, I have finally decided on an acronym-based name for ENIGMA's language, thanks to the help of a certain program written as an odd musing in CompSci. As per the recommendation of said program, I put forward Fast And Easy Compiled ENIGMA Script.

Do share your thoughts.


And yes, you tasteless nuts, the name is FAECES. Hell, it imitates GML, what do you want? ...Yes, I'm sticking with EDL. Damn. <_<

General ENIGMA / Pin tip topic
« on: January 29, 2010, 10:34:47 pm »
"Pushiness" being a lesser-used word meaning STOP TELLING ME WHAT TO DO.

A community-run-ish tips page could prove useful to some users, and in the future, could be displayed in a toggleable "Tip of the day" window. That'd be Ism's side, and I make no promises on her part.

I didn't know whether to pin it or not, as doing so seems the sort of unconsolidated, overly-friendly impeding-on-natural-right-to-figure-shit-out-on-your-own sort of move Yoyo would make. If the community sanctions the idea, though...

So, let the community speak.

Announcements / Missed one.
« on: January 11, 2010, 12:43:54 am »
  template<typename _Value>
    const _Value __numeric_traits_integer<_Value>::__min;

Should have seen that coming, really.
Errors it's trying to redeclare that, because the next token is that evil '<'.
Basically, it should just access the instantiation for that type immediately in this case, since it's already declared and all. I'll have to add a check for that come ';', but it'll be fine...

It's 01:00 and I've class tomorrow at some point. Don't worry though, it's an easy enough fix. I'm finally done with those stupid type_trait headers. ^_^

Will edit with results after this file is cleared. (Gave it a quick lookover, seems to be the only error I'll find in it).


Announcements / Happy New Year
« on: January 01, 2010, 02:55:36 am »
And a happy new decade along with that.

I just finished getting cpp_type_traits.h to parse correctly. That's an accomplishment. Along with that, however, is a regular type_traits.h, which I will be attacking next.

I don't want to give a release date after what happened last time, but I realize now that release dates are the only reason releases happen, so I guess I'm going to have to set one before the end of the month. I don't want to name the date I'm fancying now, some may be able to guess, but the rest of you can just not get your hopes up until I see what the rest of STL brings.

Anyway, a happy new year (and decade) to everyone, and quick recovery to some of my drunker friends.

...I can't stay awake much longer.
I thought this was working a minute ago, but evidently it was just something similar.

Code: [Select]
  template<bool, typename>
    struct __enable_if
    { };

  template<typename _Tp>
    struct __enable_if<true, _Tp>
    { _Tp __type; };

Honestly, it'd help to have a list of all template hacks up front. No, not just a reference on templates. A list of these goddamn hacks.

Anyway, good night.

Announcements / Merry Christmas
« on: December 25, 2009, 03:01:18 am »
I wanted to have a community-size test out today to begin the debug process, but STL provided me with more debugging goodness than I could ever have wanted.
For example, as it happens, they have created a set of templates (templates can be defined as 'crude, bitter replacements for a system that has worked for years without triangular-bracket goodness') which compare if two types are equal. It looks like this:

Code: [Select]
  template<typename, typename>
    struct __are_same
      enum { __value = 0 };
      typedef __false_type __type;

  template<typename _Tp>
    struct __are_same<_Tp, _Tp>
      enum { __value = 1 };
      typedef __true_type __type;

ENIGMA produces a loud wail if the first template above has anything in it. Yes, that's my fault entirely, but this shouldn't be a concern; these templates effectively accomplish nothing but are included by things anyway. Honestly, it's like saying string("string") just to be sure you're dealing with a string. And that's the closest I can compare it to in GML. I remeber when Dylan implemented is_real.

double is_real(double) { return true; }
double is_real(int) { return true; }
double is_real(bool) { return true; }

Anyone who understands a little about operator overloading is laughing right now, but only the truly brave are laughing at the templates above.

But anyway, it's Christmas. A time to forget how angry you are at every code input box in your vicinity, as well as the developers who made said box possible. A time to pretend that the godawful wail is actually a none-to-well-executed rendition of Jingle Bells. Best wishes to everyone; I'll probably be a few 60 miles north of here tomorrow with my lap top. Maybe sleeping, considering it's three in the morning and all I wanted was to have something to pass out today. <____<"

Instead, I'll just be passing out in general, and I welcome you all to do the same.
Merry Christmas guys, and thanks for your support.

(Maybe I can squeeze out a release by New Year's if I keep sleeping like this... [Actually, I'm better off taking the sleep])

Announcements / Hats
« on: December 22, 2009, 01:03:59 pm »
I've had to purchase two new hats today just to have something to eat each time I was dead wrong about something. It's mildly annoying, but don't worry.

That code I showed yesterday is nearly working; it ignores the second specialization for a reason I am now looking into.

Yoyo has evidently released a new version of GM, which I won't be trying number one because I hate their EULAs and number two because I'm on Ubuntu. If someone would be so kind as to provide me with a list of new functions, though, I'll see to it that they are on my todo list.

Also, serp has R3 compiling R4 correctly and is optimizing that. I rewrote var again and to my dismay, it will be very difficult to get string() working as a constructor to std::string rather than a function. I will at least attempt it, however.

I've been hoping to have a small (community) debug release soon, and Yoyo actually managing to make a release has only amplified that desire. Will post updates as they become relevant.

Announcements / Standings
« on: December 20, 2009, 07:15:09 pm »
Serp's been working on fixing up R3 with the R4 code. He's on Ubuntu, and stuff seems to just not want to work for him. The entire parser kinda stopped working for him, halting and all... Not really sure why.

As for me, I'm working on this last little piece of C++:

Code: [Select]
template<class c> struct squirrel
  int nuts;
  int tree;
squirrel<bool> epitome;

template<> struct squirrel<1>
template<> struct squirrel<2>

As soon as that parses correctly, the STL headers should all parse, and then it'll all be over.

To be honest, I'll probably have R4 done before serp finishes making R3's compiler work on Linux.

Announcements / Changes
« on: December 06, 2009, 12:22:43 pm »
Good news, everybody!!!

I've decided that after a year of development with nothing whatsoever to show, we're getting a new logo!!

Here it is! !! !

Preposterously big and annoying to the very core of your EXISTENCE. !!
Feel free to riot so I have a topic to delete! ! !!

With that, I'm increasing the price of ENIGMA roughly 150%. I don't have the figures at the moment as the math is beyond me, but it will cost more to make up for all the spending without return I've been doing!

!!1!1  !! !

Futhermore, I'm firing my Mac developer. Turns out he can't get the world's shittiest code to function on the world's shittiest operating system. A shame, I know

...what else does Sandy do that's deplorable?

You know what, screw it. That was my fun for the day.
And yes, I'm serious about the price increase. ENIGMA's new price is 0 * 1.50, which is... *crunches numbers*... $0.00.

Oh, and I think maybe I'll stick to the old logo.

Also, miky reminded me of an additional disclaimer. Mac isn't really the shittiest OS; I think Vista earned that title when it did away with HLP. "The Help for this program was created in Windows Help format, which was used in previous versions of Windows and it is not supported in Windows Vista." Though, I'm actually on Vista now... At least it boots. World's shittiest OS... Bah, I'll think on it. Really, I'm just mad because it's been a pain trying to get XLib things to compile on it.

Good day. ^_^

I figure I'll insert the point of this message. Yes, it's 90% troublemaking, but more importantly, there's a lesson in the other 10%.
I know development has taken a while, but progress has been made. It's also a bit more visible than Yoyo's, as you can follow it in the SVN if you really like.

Remember that this project started not long after the release of GM7. In the meantime, I've released three times, they have released nothing. This latest release has been done to refurbish, rethink, and recode everything. Yoyo's just porting GM with help from free software. Think about it. They have $2 million to form a team. A team of "professionals." They claim they're not struggling... Heh, I even tell people what's going on at the moment.

Speaking of. Presently, I need to logically relocate a large block of code that handles identifiers in order to tolerate ::, an integral part of C++. No one said parsing C++ would be without incident. Once the libs parse right, there's really nothing standing in the way.


Announcements / Victory
« on: November 27, 2009, 03:24:50 pm »
Code: [Select]
No error.
Parse time: 380 milliseconds

Macros (518) [+]
Variables [+]
Define: acos
  acos:  Function with 1 parameters, returning double  Dereference path: (params = 1)</group>

After I had what I thought to be the basics down, all the Windows C headers parsed without error. The Linux ones, however... It was a constant uphill battle.
Math.h employs such faggotry as calling __CONCAT on itself, which only works if it's called internally as an alias. For example, the first code works, the second does not:

Code: [Select]
#define __CONCAT(a, b) a ## b
#define TRIPLE_CONCAT(a,b, c) ALIAS_CONCAT( __CONCAT(a,b),c)
#define ALIAS_CONCAT(a, b) __CONCAT(a,b)
Code: [Select]
#define __CONCAT(a, b) a ## b
#define TRIPLE_CONCAT(a,b, c) __CONCAT( __CONCAT(a,b),c)

I'm not entirely sure why, really, and I don't care. Both work for me, and I see no reason to change it just because GCC only likes the first.

Anyway, more work to do. (Along with two research papers and a "scientific" paper to write). I'm a bit swamped, as usual.

Pages: « 1 2 3 4 5 6 7 8 9 10 11 12 13 »