Pelles C forum

Pelles C => Add-ins => Topic started by: czerny on January 03, 2012, 02:52:30 AM

Title: PreProc
Post by: czerny on January 03, 2012, 02:52:30 AM
Hallo,

I would like to learn, how to write AddIns.
It would be nice if someone could check my work. The first is a minimal AddIn. May be it can be a starting point for someone. The second  one runs the Preprocessor.

czerny

Title: Re: PreProc
Post by: TimoVJL on January 03, 2012, 10:50:18 AM
In AddInCommand()  instead of ShellExecute() you can use CreateProcess()
Code: [Select]
...
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
...
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (CreateProcess(NULL,szTmp,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
_tcscpy(szPara,adi.szFilename);
AddIn_OpenDocument(hwndMain, AID_SOURCE, GetIFile(szPara));
} else AddIn_WriteOutput(hwndMain, _T("error"));
...
EDIT:
Use AddInCommandEx()  instead of AddInCommand() for Win64 compability.
Title: Re: PreProc
Post by: czerny on January 03, 2012, 06:18:10 PM
Thank you timovjl,

I have changed this and uploaded a corrected version.

czerny
Title: Re: PreProc
Post by: TimoVJL on January 04, 2012, 10:15:37 AM
Please upload corrected PreProc again.
There was ppj-file only.
Title: Re: PreProc
Post by: czerny on January 04, 2012, 03:39:57 PM
sorry!
Title: Re: PreProc
Post by: TimoVJL on January 04, 2012, 05:09:34 PM
If you want to use current project CCFLAGS too:
Code: [Select]
...
static HWND hwndProj = NULL;
...
case AIE_PRJ_CREATE:
// Remember project window handle, in case we need it.
hwndProj = hwnd;
return TRUE;

case AIE_PRJ_DESTROY:
// Forget project window handle.
hwndProj = NULL;
return TRUE;
...
AddIn_GetIDEFolder(hwndMain, ADDIN_FOLDER_BIN, szTmp, sizeof(szTmp)/sizeof(szTmp[0]));
_tcscat(szTmp, _T("\\pocc.exe /P "));
if (hwndProj && AddIn_GetProjectSymbol(hwndProj, _T("CCFLAGS"), szTmp1, sizeof(szTmp1)/sizeof(szTmp1[0]))) {
_tcscat(szTmp, szTmp1);
_tcscat(szTmp, _T(" "));
}
...
Title: Re: PreProc
Post by: czerny on January 04, 2012, 05:56:11 PM
Thank you!

I would'nt have found howto get things like CCFLAGS.

My first cause to make this addin was, to test preprocessor macros. But yesterday I had problems to compile the newest zlib library. I had some suspicion that a macro OF(arg) is not working right and  than I would have needed the real flags.

czerny
Title: Re: PreProc
Post by: CommonTater on January 04, 2012, 07:07:21 PM
Look in the AddIn SDK helpfile

You could quite easily...
use AddIn_GetProjectSymbol()  to get the original CCFLAGS and save them
change the CCFLAGS to your liking with AddIn_SetProjectSymbol()
Send AddIn_SendIDECommand() with AIC_PROJECT_COMPILE
Trap the AddIn_Main token for AIE_PROJ_ENDBUILD
Then use AddIn_SetProjectSymbol() to restore the original CCFLAGS

No messing with ShellExecute or CreateProcess at all...
Title: Re: PreProc
Post by: czerny on January 05, 2012, 12:37:30 AM
Hallo Commontater,

I tried your suggestion but get a little  problem.

Code: [Select]
if (hwndProj && AddIn_GetProjectSymbol(hwndProj, _T("CCFLAGS"), ccFlags, sizeof(ccFlags)/sizeof(ccFlags[0]))) {
_tcscpy(szTmp, _T("/P "));
_tcscat(szTmp, ccFlags);
AddIn_SetProjectSymbol(hwndProj, _T("CCFLAGS"), szTmp); //set
AddIn_GetProjectSymbol(hwndProj, _T("CCFLAGS"), szTmp, sizeof(szTmp)/sizeof(szTmp[0])); //check
AddIn_WriteOutput(hwndMain, szTmp);
AddIn_SendIDECommand(hwndMain, AIC_PROJ_COMPILE); //build
AddIn_SetProjectSymbol(hwndProj, _T("CCFLAGS"), ccFlags); //reset
AddIn_WriteOutput(hwndMain, ccFlags);
}

Project saved: D:\C\wwl\ide-extensions\extensions\PreProc\PreProc.ppj
/P -W1 -Ot -Gz -Ze -Tx86-coff
Project saved: D:\C\wwl\ide-extensions\extensions\PreProc\PreProc.ppj
-W1 -Ot -Gz -Ze -Tx86-coff
Project build started
Project build ended successfully

It seems as if I have to wait until the file is compiled. Is there a simple  solution?

czerny
Title: Re: PreProc
Post by: Stefan Pendl on January 05, 2012, 01:16:04 AM
It seems as if I have to wait until the file is compiled. Is there a simple  solution?

I think you omitted the stage below:
Trap the AddIn_Main token for AIE_PROJ_ENDBUILD

Reread Taters suggestion.
Title: Re: PreProc
Post by: CommonTater on January 05, 2012, 01:48:07 AM
Yep... you want this to be event driven...

1) don't add the button until a project is created/opened AddIn_Main()  ...AIE_PROJ_CREATE
2) don't do anything until the button is pressed.
3) when the button is pressed flip the CCFLAGS and set a flag
4) start the compile
5) do nothing.
6) when AddIn_Main signals AIE_PROJ_ENDBUILD ... then put the strings back only if he flag is set

AddIn_Main is a message tosser... use it like you would the WinProc in a windows program.

Also, beware of syntax like this...
Code: [Select]
AddIn_GetProjectSymbol(hwndProj, _T("CCFLAGS"), szTmp, sizeof(szTmp)/sizeof(szTmp[0])); //check
Size of only works on arrays in scope... if you aren't extremely careful you'll end up with the size of the pointer instead of the size of the array...  It's better to us a #define such as ... #define MAX_CCFLAGS 128 ... both when defining the string and when referring to it's size than to try clever sizeof() tricks.




Title: Re: PreProc
Post by: czerny on January 05, 2012, 04:49:19 PM
Ok,

I have made a lot of changes (new version uploaded). But it remains a problem:

A file that is not part of the project (tst.c for example) will not be compiled by AddIn_SendIDECommand().

I see three different ways to handle this.

Check, if file is part of the project. If so than
1.) do nothing (not so good) or
2.) include it in the project -- compile -- exclude  it again or
3.) invoke pocc as in my first attempts.

Is there an other solution? Some idees?

czerny
Title: Re: PreProc
Post by: TimoVJL on January 05, 2012, 05:32:52 PM
Least with AddIn_EnumProjectFiles you can verify if file is part of project.
If it is not then you can process it with some default values with that another way.
Title: Re: PreProc
Post by: czerny on January 05, 2012, 06:35:07 PM
This would be the 3. way. But I do not like to have two ways than to invoke the preprocessor.
Should I return to CreateProcess alone?

czerny
Title: Re: PreProc
Post by: czerny on January 07, 2012, 01:28:58 PM
I have two questions to AddIn_EnumProjectFiles:
When is this function returning TRUE or FALSE resp.?

What about the return value of the callback function? It seems to me, that a return FALSE stops enumeration. Is this right?

A second point:

Try this with the actual version.
Rename Preproc.c to say Preproc_Tmp.c
Then click the Preproc Button
Why is AddIn_SendIDECommand not invoked then?

A  third point:

If  I enum project files, the file tst.c (which is excluded) is also listed.
How can I check, if a file is excluded?

czerny
Title: Re: PreProc
Post by: CommonTater on January 07, 2012, 01:50:38 PM
I have two questions to AddIn_EnumProjectFiles:

When is this function returning TRUE or FALSE resp.?
I haven't done a lot with this macro, but it would make sense for it to return true when it is returning a file and false when it's not... probably you'll get false at the end of the enum as a loop control, but the easy way is to try it and find out.

Quote
What about the return value of the callback function? It seems to me, that a return FALSE stopps enumeration. Is this right? Is this value returned by AddIn_EnumProjectFiles?

The callback is provided by you... and, again you need to test it to be sure, but I would think a return of false would stop the enum.

The AddIn SDK help file isn't terribly clear on this...

Quote
A  third point:
If  I enum project files, the file tst.c (which is excluded) is also listed.
How can I check, if a file is excluded?

While the AddIn mechanism is pretty flexible it's not perfect... take a look at the uFlags item in the struct, about your best bet if you're only wanting to run the preprocessor is to use the enum dependent files feature... not the enum all files.

Just a thought... but you might want to set it up to only run the preprocessor on the currently active file in the IDE...
 
Title: Re: PreProc
Post by: czerny on January 07, 2012, 02:46:09 PM
Quote
I haven't done a lot with this macro, but it would make sense for it to return true when it is returning a file and false when it's not... probably you'll get false at the end of the enum as a loop control, but the easy way is to try it and find out.

What I get is always TRUE. I have hopped that it forwards the callback return. So I have to signal my search result over a global variable.

Quote
While the AddIn mechanism is pretty flexible it's not perfect... take a look at the uFlags item in the struct

If it is fuFlags, what you mean, this is of no help. I use
Code: [Select]
aepf.fuFlags = EPFF_DEPENDENT_FILES;and I think that tst.c should not in this file set because  it is excluded. But it is!


Quote
use the enum dependent files feature... not the enum all files

I have done this! See above.

czerny
Title: Re: PreProc
Post by: czerny on January 07, 2012, 02:58:05 PM
I want to show my enum code. My be this is from help:

Code: [Select]
ADDIN_ENUM_PROJECT_FILES aepf = { 0 };

aepf.cbSize = sizeof(aepf);
aepf.fuFlags = EPFF_DEPENDENT_FILES;
aepf.pfnCallback= pfn;
aepf.pvData = szTmp; // actual files name
if (hwndProj && AddIn_EnumProjectFiles(hwndProj, &aepf))
AddIn_WriteOutput(hwndMain, _T("True"));
else
AddIn_WriteOutput(hwndMain, _T("False"));

and

Code: [Select]
BOOL pfn(LPCTSTR pszFilename, LPVOID pvData)
{
return !(_tcscmp(pszFilename, (TCHAR *)pvData)==0);
}


czerny
Title: Re: PreProc
Post by: czerny on January 08, 2012, 02:20:07 PM
ok, I do not find a way to distinguish between ex- and included project files, I will go back to invoke pocc per CreateProcess.
If somebody finds something to the rename problem (s.a.) or the ex-, include difference I would be glad to hear from.

czerny
Title: Re: PreProc
Post by: CommonTater on January 08, 2012, 03:12:56 PM
I'm sorry... I don't catch the relationship here... if you can't enumerate included files you have to use create process...  Why? 

Just start a build operation using the current file AddIn_GetActiveDocument and the preprocessor flags, as I explained earlier... It's pretty simple, click on the file you want to pre-process then click your button.  I sincerely don't see why you need to enumerate files and/or worry about anything except the active document...


Title: Re: PreProc
Post by: czerny on January 09, 2012, 12:44:51 AM
1. If I try to compile a file which is part of the project but excluded the compilation is not executed and the flags are therefor not restored.
2. if I have an regular (included) file, loaded in a edit window, than rename this file in project window and then invoke preproc I get the same error.

czerny
Title: Re: PreProc
Post by: CommonTater on January 09, 2012, 01:19:33 AM
Post your code... lets see what you're doing...
Title: Re: PreProc
Post by: czerny on January 09, 2012, 01:23:20 AM
replace preproc-cp.c with preproc-pr.c.

czerny
Title: Re: PreProc
Post by: CommonTater on January 09, 2012, 03:57:45 AM
Ok... what you want is probably something very close to this...

Note, this has been tested only very cursorily, no promises it will work exactly as you want, but it should give you the general idea... (i.e. there's bound to be a bug in there someplace.)
 
Title: Re: PreProc
Post by: TimoVJL on January 09, 2012, 02:15:43 PM
With this code you can borrow more options from current project for external file:
Code: [Select]
TCHAR *GetIFile(TCHAR *szFileName)
{
TCHAR *szTmp;

if (*szFileName)
{
szTmp = _tcsrchr(szFileName, '.');
*(++szTmp) = 'i';
*(++szTmp) = '\0';
}
return szFileName;
}

void ExecutePOCC(void)
{
HWND hwnd;
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
ADDIN_DOCUMENT_INFO adi = { .cbSize = sizeof(adi) };
TCHAR szTmp[MAX_PATH*3];
TCHAR szTmp2[1024];

hwnd = AddIn_GetActiveDocument(hwndMain);
if (!hwnd) return;
if (!AddIn_GetDocumentInfo(hwnd, &adi)) return;
if ((adi.fDirty) || (!adi.szFilename[0]))
AddIn_SendIDECommand(hwndMain, AIC_FILE_SAVE);
if (!AddIn_GetDocumentInfo(hwnd, &adi)) return;
int nLen = AddIn_GetIDEFolder(hwndMain, ADDIN_FOLDER_BIN, szTmp, sizeof(szTmp)/sizeof(TCHAR));
_tcscat(szTmp, _T("\\pocc.exe -P "));
nLen += 13;
if (hwndProj && AddIn_GetProjectSymbol(hwndProj, _T("CCFLAGS"), &szTmp[nLen], sizeof(szTmp)/sizeof(TCHAR)-nLen)) {
_tcscat(szTmp, _T(" "));
AddIn_GetProjectSymbol(hwndProj, _T("INCLUDE"), szTmp2, sizeof(szTmp2)/sizeof(TCHAR));
SetEnvironmentVariable(_T("INCLUDE"), szTmp2);
AddIn_GetProjectSymbol(hwndProj, _T("LIB"), szTmp2, sizeof(szTmp2)/sizeof(TCHAR));
SetEnvironmentVariable(_T("LIB"), szTmp2);
}
_tcscat(szTmp, adi.szFilename);

//AddIn_WriteOutput(hwndMain, NULL);
AddIn_ClearOutput(hwndMain);
AddIn_WriteOutput(hwndMain, szTmp);

si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (CreateProcess(NULL,szTmp,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
_tcscpy(szTmp,adi.szFilename);
AddIn_OpenDocument(hwndMain, AID_SOURCE, GetIFile(szTmp));
} else AddIn_WriteOutput(hwndMain, _T("error"));
}
Title: Re: PreProc
Post by: czerny on January 09, 2012, 05:56:35 PM
hi timovjl,

if I understand your snippet right, this is just a info what else I can get from the project options.

It is NOT a solution to one of my problems, right?

czerny
Title: Re: PreProc
Post by: czerny on January 09, 2012, 06:14:57 PM
Tater,

have you installed and checked your version?
I have not much time now. Will have a closer lock to night.

But as a quick view

1. There is no button
2. There is a /P option with every compile

czerny
Title: Re: PreProc
Post by: czerny on January 09, 2012, 10:51:38 PM
Hallo CommonTater,

your snippet shows the same behaviour.

1. A just renamed file (in the project panel) doesn't compile.
2. A excluded file doesn't compile too.

czerny
Title: Re: PreProc
Post by: CommonTater on January 09, 2012, 11:41:59 PM
Tater,

have you installed and checked your version?
I have not much time now. Will have a closer lock to night.

But as a quick view

1. There is no button
2. There is a /P option with every compile

czerny

I did check it here... but only so far as to make sure it compiled and did something resembling the desired function... I was not trying to provide you a working solution, just a direction to take in your project.  It is YOUR project, I'm not going to "steal your thunder".

My thought was for you to study the code and see the process, not to copy and paste it into your own project.
 
Excluded projects won't compile because they have no project "shells" for the compiler to use... Look at a project file in notepad, you will find that extra files and excluded files are listed in a special section at the bottom, apart from the active sections at the top.  (FWIW... the project file is also a sort of makefile)
 
Title: Re: PreProc
Post by: czerny on January 10, 2012, 12:23:14 AM
Hi CommonTater,

it is clear to me, that an excluded file shouldn't be compiled by design. But this is not what I want.
I would like to write a test file with a macro to test and see, if it works. Such a test file should NOT be part of the project I am working on. So an excluded file needs to be compiled via CreateProcess.

On the other side it could be of use, to see the preprocessors result of a regular project. Than the AIC_PROJ_COMPILE way would be better.

But to differentiate between this two situations I have to parse the project file.

It remains the renaming problem. I consider this as a bug.

Can you verify this behaviour?

czerny
Title: Re: PreProc
Post by: CommonTater on January 10, 2012, 12:36:37 AM
That's not a bug. 

POIDE is almost entirely project driven. It would not make sense to let you compile or process files that are not part of an active project... I seriously doubt Pelle even considered it when writing the IDE (I wouldn't have).

LOL... I gotta hand it to you... you sure do come up with some odd-ball problems!


Title: Re: PreProc
Post by: TimoVJL on January 10, 2012, 10:59:28 AM
Quote
1. A just renamed file (in the project panel) doesn't compile.
After renaming you have to reopen the file before compiling ? feature ?

Quote
if I understand your snippet right, this is just a info what else I can get from the project options.
In that way i can compile my test files with projects options even they are not included to project. (It can be used for files in project too ?) Just for example.
Title: Re: PreProc
Post by: czerny on January 10, 2012, 01:17:02 PM
tater:
Quote
POIDE is almost entirely project driven. It would not make sense to let you compile or process files that are not part of an active project... I seriously doubt Pelle even considered it when writing the IDE (I wouldn't have).

I do not want process files from INACTIVE projects. I want process EXCLUDED files from ACTIVE projects. And it is clear to me that that is not normaly available. I have said that before.

timovjl:
Quote
Quote
    1. A just renamed file (in the project panel) doesn't compile.
After renaming you have to reopen the file before compiling ? feature ?
If this is the case, then it happend normally behind the scenes. If one renames a file, there isn't any prompt 'should I reload file?'

There should be the ADDIN_DOCUMENT_INFO.fDirty flag set. The file name should be marked with an asterisk resp.

czerny
Title: Re: PreProc
Post by: czerny on January 10, 2012, 02:57:33 PM
My english isnot very good, so it may be that I hav not accurate discribed what I want to know.

So I will ask it more exactly:

How can I detect if a file (included member of an open project) is just renamed in the project panel?

czerny

Title: Re: PreProc
Post by: CommonTater on January 10, 2012, 03:14:37 PM
Your best plan might be to simply make a second project with your test file(s) as an active document... You can always recycle the same project by including it in different workspaces...

The workspace editor makes this easy as you can just drag and drop the project into the editor's list.
Title: Re: PreProc
Post by: czerny on January 10, 2012, 04:10:33 PM
I have done this yet.  That is the cause for my question.

Another observation:

1. Load an arbitrary project.
2. Load one of its files in the editor.
3. Rename this file (this is regognized at the editor tab)
4. Rename the same file once more (this is not regognized)

czerny
Title: Re: PreProc
Post by: czerny on January 10, 2012, 04:39:36 PM
Here is a little test project.

czerny