# how to avoid macro loops

## Recommended Posts

If found some source code that has this in it

#define FOR(q,n) for(int q=0;q<n;q++)
#define SFOR(q,s,e) for(int q=s;q<=e;q++)
#define RFOR(q,n) for(int q=n;q>=0;q--)
#define RSFOR(q,s,e) for(int q=s;q>=e;q--)
#define ESZ(elem) (int)elem.size()

and it is used as

const char** sProgram = new const char*[ESZ(sLines)];
FOR(i, ESZ(sLines))sProgram[i] = sLines[i].c_str();

How should i make these loops so i dont have to use these macros?
I tried this

const char** sProgram = new const char* [(int)sLines.size()];

int i = 0;
for(i; sLines.size(); i++)
sProgram[i] = sLines[i].c_str();

but the for loop gets vector out of bounds error when it hits last line in file (this is used in function that reads text file)

##### Share on other sites

for(i; i < sLines.size(); i++)

L. Spiro

##### Share on other sites

ok thanks sorry for asking stupid question

##### Share on other sites

In case you use GCC, you can compile with -save-temps to trivially figure out any macro abuse, no matter how convoluted it is. For every file foo.c you will find a file foo.ii generated, which contains the output of the preprocessor (i.e. with everything included, and all macros expanded). I've found this immensely helpful at times.

##### Share on other sites

I'm with Servant of the Lord on this. Are you really sure you need to do this?

Sometimes you have to question the quality of your sources. In this case, it's not only converting away from std::string to unsafe raw strings that is a code smell, but the use of macros in this situation also smells nasty. Macro usage like this can conceal or even introduce bugs, and detracts from readability, making it a confusing mess for no real reason other than somebody thought they could save some typing. If they took shortcuts there, the remainder of their code might be smelly, too.

What is it you are trying to accomplish in the larger scheme? Maybe we can help you figure out a less smelly method.

##### Share on other sites
Well it is 'simple' process - the function opens file for reading, reads through entire file with this

// get all lines from a file
vector<string> sLines;
char sLine[255];
while(fgets(sLine, 255, fp))sLines.push_back(sLine);
fclose(fp);

then it does this

const char** sProgram = new const char* [(int)sLines.size()];

int i = 0;
for(i; i < sLines.size(); i++)
sProgram[i] = sLines[i].c_str();

and processes entire file as needed and does

delete[] sProgram;

now when i look at this I see that I never free sLines vector is that needed? Edited by proanim

##### Share on other sites

Ok i made changes and now same stuff happens only difference is now i can't complete the entire process. There is no error or anything the funtion returns false

bool CShader::loadShader(string sFile, int a_iType)
{
//FILE* fp = fopen(sFile.c_str(), "rt");
//if(!fp)return false;

// get all lines from a file
vector<string> sLines;
//char sLine[255];
//while(fgets(sLine, 255, fp))sLines.push_back(sLine);
//fclose(fp);

ifstream infile(sFile.c_str());

while(!infile.eof())
{
string s;
getline(infile, s);
sLines.push_back(s);
}

infile.close();

//const char** sProgram = new const char*[ESZ(sLines)];
//FOR(i, ESZ(sLines))sProgram[i] = sLines[i].c_str();

//const char** sProgram = new const char* [(int)sLines.size()];
vector<const char *> sProgram;

//for(int i; i < sLines.size(); i++)
//	sProgram[i] = sLines[i].c_str();
for(unsigned int i=0; i<sLines.size(); ++i)
sProgram.push_back(sLines[i].c_str());

//delete[] sProgram;

int iCompilationStatus;

if(iCompilationStatus == GL_FALSE)return false;
iType = a_iType;

return 1;
}

What can cause glGetShaderiv(uiShader, GL_COMPILE_STATUS, &iCompilationStatus); to fail ? Shader files that i use with this are basic color shaders and they work with orginal function but now they fail to compile, I am not sure why exactly.

##### Share on other sites

Per the manual page on glCompileShader you can call glGetShaderInfoLog to get some information on why the compile might have failed.

##### Share on other sites

Well all I can get from glGetShaderInfoLog is '00B4A520' or similar ???

##### Share on other sites

Why don’t you show the code you are using to get said results?

So why not save a reply and also post the shader code since that seems more likely to be the source of the error?

L. Spiro

Edited by L. Spiro

##### Share on other sites
So why not save a reply and also post the shader code since that seems more likely to be the source of the error?

Shaders are working in first version of the function

#version 330

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inColor;

smooth out vec3 theColor;

void main()
{
gl_Position = vec4(inPosition, 1.0);
theColor = inColor;
}

#version 330

smooth in vec3 theColor;
out vec4 outputColor;

void main()
{
outputColor = vec4(theColor, 1.0);
}

// Load shaders and create shader program


##### Share on other sites
Well all I can get from glGetShaderInfoLog is '00B4A520' or similar ???
Why don’t you show the code you are using to get said results?

L. Spiro

##### Share on other sites

What L. Spiro is saying, in case it's not obvious, is that you're not showing how you're getting this error log back...  Your earlier post shows some good info on how you're compiling your shader, but it doesn't show how you're obtaining that strange error log.

It's kinda like trying to diagnose a patient, if you're a doctor, and he says "I have symptoms" but doesn't say what those symptoms are :)

Edited by Cornstalks

##### Share on other sites
glShaderSource(uiShader, sLines.size(), &sProgram[0], NULL);

int infologLength;
int maxLength;
char* infoLog;

ofstream outfile;
outfile.open ("log.txt");
outfile << &infoLog << endl;
outfile.close();

##### Share on other sites

Santa01 showed above how to get the log from the shader or program object. Your code has two major problems though:

1. glGetShaderInfoLog expect you to allocate the buffer so that it can write the log to it. You're not allocating anything and so the function is writing to wherever the pointer happens to point. In this case, it's trashing the stack big time.
2. infoLog is char *, and so infoLog itself is the string containing the log, not &intoLog. Output as a string is only overloaded for char * (with combinations of cv-qualifiers), but &infoLog is a char **  which just prints the address of the infoLog variable.

##### Share on other sites

finally, so the errors are this

Fragment shader failed to compile with the following errors:
ERROR: 2:1: error(#307) Profile "smooth" is not supported
ERROR: 2:1: error(#76) Syntax error: unexpected tokens following #version
ERROR: error(#273) 2 compilation errors.  No code generated


any ideas?

##### Share on other sites

Specifically:
getline(infile, s);
should be:
getline(infile, s);
s.append( endl );
I had assumed originally that ::glShaderSource() would treat each line you passed to it as…a line.
But closer reading reveals that all it does is put all the lines back together just as you pass them to the function, which means if you don’t have line endings then it will be passed to the compiler as a shader written entirely on one line. The reason it sees “330” and “smooth” as separate identifiers is because there is a hidden \r between them that was not discarded by getline(), but inside the shader/compiler that does not constitute a new line, so it basically sees this: “#version 330 smooth in vec3 […]”.

You load the whole file, expand it into an array of lines (which removes the \n line-ending), make another array of pointers into that, then pass that whole thing to OpenGL, and all OpenGL does internally is make it all back into one single long line of text, which is exactly what you had (minus new lines) when you loaded it directly from the file in the first place before you did all that mess of array creation and line-by-line parsing.

You basically spent a lot of time writing a complex loader whose only purpose is to remove new-lines and create bugs.
Why not do as I suggested and just load the file directly to memory, append a 0, and pass it as-is with no further parsing to OpenGL?
santa01 showed you how to do it.  It is 10 times less complex, 100 times faster, and 10 times less error-prone.

L. Spiro Edited by L. Spiro

##### Share on other sites

It works with s.append("\n"); no problem.

Also when I try to read the file as santa01 suggested there is something wierd happening. When function gets vertex shader it reads through it and exits just before

    theColor = inColor;
}

I never used this approach so I might be missing something.

##### Share on other sites

Are you phil67rpg?

If you made changes to your code and you have new errors, post the new code.  It helps us not to take shots in the dark when trying to guess what your problem could be.

Anyway it sounds as though you either forgot to add the 0 or you added the 0 but at a fixed position.

I surely hope you did not forget the 0 because I mentioned it twice and it was included in the santa01’s code.

If you are inserting it at a fixed or miscalculated position it would explain why one shader is too short and the other is too long.

Again, nothing but conjecture until we see some code.

L. Spiro

##### Share on other sites

This is the code I used

ifstream file(sFile.c_str(), ios::binary);

file.seekg(0, ios::end);
int sourceLength = file.tellg(); // warning C4244: 'initializing' : conversion from 'std::streamoff' to 'int', possible loss of data
GLchar* shaderSource = new GLchar[sourceLength + 1];

file.seekg(0, ios::beg);

file.close();

GLint compileStatus;

if (compileStatus == GL_FALSE)
{
GLint infoLogLength;

GLchar* infoLog = new GLchar[infoLogLength + 1];

ofstream outfile;
outfile.open ("log.txt");
outfile << infoLog << endl;
outfile.close();

delete[] infoLog;
}

it is almost exactly the same as santa01's.

You say that santa01's code did include 0 (where is it?)

##### Share on other sites
it is almost exactly the same as santa01's.

You say that santa01's code did include 0 (where is it?)

Its on line:

shaderSource[sourceLength] = 0;

which does present in your sources...

you can always print shaderSource to stdout to see if there is any extra crap in the buffer. its also useful to look through the shaderSource contents in your IDE under debug, IDEs do usually print special character with their symbolic representation like \r\n etc. for instance if you develop under MacOS X you gonna have \r whereas shader compiler could expect \n instead, hence compilation errors.

and it definitely won't harm to examine shader source file in hex editor to check its real contents :)

##### Share on other sites

When i print the content of shaderSource to file with

ofstream outfile;
outfile.open ("log.txt", fstream::out | fstream::app);
outfile << endl;
outfile.close();

I get normal contents of vertex and fragment shader - no extra symbols or anything.

But when I use debugger I see this

and this

any ideas?

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628288
• Total Posts
2981845

• 11
• 10
• 10
• 11
• 17