This Topic is deprecatedAccording to SlickCMacroBestPractices.pdf modifying system macros is not recommended
Modifying macros that ship with SlickEdit
Don't do it! Take your hands away from the keyboard. Unless you have an OEM support contract with SlickEdit Inc., and sometimes not even then, you should not be modifying system macros...ever. Feel free to use snippets from them all you like in your own macros, but don't modify the ones we ship.
If you modify a system macro, you are guaranteeing that:
• The next patch or upgrade you do willwipe out your changes
• Support will not be able to help you
To import Keil uVision workspaces please see http://community.slickedit.com/index.php?topic=2382.0
Since I am working with an IDE which is not yet supported by SlickEdit I have investigated some time to get rudimentary support for these project files and want to share my knowledge with other people who probably want to add support for other IDEs.
This HowTo is about support for Keil uVision2 project files but can be adapted to any other project file with a similar structure. Currently it is possible to open the project file with SlickEdit - the source files are automatically grouped using SlickEdit's "Package View".
At the moment I am sure that some modifications are unnecessary, quick and dirty or erroneous but I will try to improve this HowTo as soon as I have new information.
1. Let's take a look at a Keil project file 'demo.uv2'...... so the .uv2 project files are simple text files starting with this two ### lines followed by a target definition section, followed by a group definition section, followed by a section containing the project's sources which are .c and and .a51 (8051 Assembly).
### uVision2 Project, (C) Keil Software
### Do not modify !
Target (demo), 0x0000 // Tools: 'MCS-51'
Group (C Sources)
Group (A51 Sources)
File 1,7,<.\src\c\foo.c><foo.c> 0x0
File 2,2,<.\src\a51\foo.a51><foo.a51> 0x0
...
2. Modifications in the file 'slick.sh'In this file we have to:
- add a define for the project file extension (.uv2)
- add a define for the vendor name
#define KEIL_PROJECT_EXT '.uv2'
#define KEIL_VENDOR_NAME 'keil uvision2'
3. Modifications in the file 'wkspace.e'Here we have to do the most work...
3.1 Modifications in the 'VendorNameTable' arrayHere we have to make the assignment of our project file's extension to the vendor name by adding a line
KEIL_PROJECT_EXT => KEIL_VENDOR_NAME,
3.2 Modifictions in the 'workspace_open' function3.2.1 Adapt the 'format_list' string assignmentInsert your project file's extension in here - in my case the string would now look like this:
format_list='Workspace Files(*'WORKSPACE_FILE_EXT';*'VISUAL_STUDIO_SOLUTION_EXT';*'VCPP_PROJECT_WORKSPACE_EXT';
*'VCPP_EMBEDDED_PROJECT_WORKSPACE_EXT';*'TORNADO_WORKSPACE_EXT';*'JBUILDER_PROJECT_EXT';
*'MACROMEDIA_FLASH_PROJECT_EXT'),SlickEdit Workspace Files(*'WORKSPACE_FILE_EXT'),
SlickEdit Project Files(*'PRJ_FILE_EXT'),
Visual C++ Workspace Files(*'VCPP_PROJECT_WORKSPACE_EXT'),
Visual C++ Embedded Workspace Files(*'VCPP_EMBEDDED_PROJECT_WORKSPACE_EXT'),
Tornado Workspace Files(*'TORNADO_WORKSPACE_EXT'),
JBuilder Project Files(*'JBUILDER_PROJECT_EXT'),
Flash Project Files(*'MACROMEDIA_FLASH_PROJECT_EXT'),
Keil Project Files(*'KEIL_PROJECT_EXT'),
All Files('ALLFILES_RE')';
3.2.2 Perform the workspace associationThere is a code block...
} else if (file_eq('.'get_extension(WorkspaceFilename),XCODE_PROJECT_EXT)) {
status=_WorkspaceAssociate(WorkspaceFilename);
if (status) {
return(status);
}
}
after this block add another >else if< construct with your workspace
} else if (file_eq('.'get_extension(WorkspaceFilename),KEIL_PROJECT_EXT)) {
status=_WorkspaceAssociate(WorkspaceFilename);
if (status) {
return(status);
}
}
3.3. Add a workspace_open_... functionThe next step is to add a custom workspace_open_... function - I have added it after the 'workspace_open_xcode' function which I have used as template.
_command int workspace_open_keiluv2(_str workspaceFilename = "") name_info(FILE_ARG'*,')
{
_macro_delete_line();
// pass the call
return workspace_open_other(workspaceFilename, "Open Keil Project",
"Keil Project Files(*"KEIL_PROJECT_EXT"),All Files("ALLFILES_RE")");
}
3.4. Modifications in the '_getAssociatedProjectConfigs' function3.4.1. Set the makefiletypeThere is a code block
}else if (file_eq(ext,XCODE_PROJECT_EXT)) {
makefiletype = XCODE_VENDOR_NAME;
append a block for your project type
} else if (file_eq(ext,KEIL_PROJECT_EXT)) {
makefiletype = KEIL_VENDOR_NAME;
3.4.2. Get project configurationThis functionality does not work yet but I already have the changes in here...
After the block
} else if (makefiletype==XCODE_VENDOR_NAME) {
return _xcode_get_configs(associateMakefile,configList);
add
} else if (makefiletype==KEIL_VENDOR_NAME) {
return _keil_get_configs(associateMakefile,configList);
3.5 Modifications in the 'GetCompilerPackage' functionThis functionality is also not supported yet but I have done some preparations in here...
after block
case XCODE_VENDOR_NAME:
return "Apple Xcode";
add
case KEIL_VENDOR_NAME:
return "Keil uVision";
3.6. Modifications in the '_WorkspaceAssociate' function3.6.1. Set WorkspaceType...After
} else if (_IsXcodeProjectFilename(VendorWorkspaceName)) {
WorkspaceType=VendorNameTable:[XCODE_PROJECT_EXT];
add
} else if (_IsKeilProjectFilename(VendorWorkspaceName)) {
WorkspaceType=VendorNameTable:[KEIL_PROJECT_EXT];
3.6.2. Set Compiler...After
}else if (WorkspaceType == XCODE_VENDOR_NAME) {
Compiler=GetCompilerPackage(WorkspaceType);
add
}else if (WorkspaceType == KEIL_VENDOR_NAME) {
Compiler=GetCompilerPackage(WorkspaceType);
3.6.3. Extend the If clause if (_IsVisualStudioProjectFilename(CurFilename) ||
file_eq('.'get_extension(CurFilename),VCPP_PROJECT_FILE_EXT) ||
file_eq('.'get_extension(CurFilename),VCPP_EMBEDDED_PROJECT_FILE_EXT) ||
file_eq('.'get_extension(CurFilename),TORNADO_PROJECT_EXT) ||
file_eq('.'get_extension(CurFilename),JBUILDER_PROJECT_EXT) ||
file_eq('.'get_extension(CurFilename),XCODE_PROJECT_EXT)||
file_eq('.'get_extension(CurFilename),MACROMEDIA_FLASH_PROJECT_EXT)) {
by an entry for your project file
file_eq('.'get_extension(CurFilename),KEIL_PROJECT_EXT)
3.6.4. Apply the XCODE hack for our project fileAfter
if (file_eq('.'get_extension(CurFilename),XCODE_PROJECT_EXT)) {
_xcode_get_configs(absolute(ProjectNames[i],WorkspacePath),configList);
add an else tree
} else if (file_eq('.'get_extension(CurFilename),KEIL_PROJECT_EXT)) {
_keil_get_configs(absolute(ProjectNames[i],WorkspacePath),configList);
3.7. Modifications in the 'GetFilenamesFromVendorWorkspaceFile' function
After
case XCODE_VENDOR_NAME:
ret_value=_xcode_get_target_names(VendorWorkspaceFilename,ProjectNames,VendorProjectNames);
break;
add a case for our workspace
case KEIL_VENDOR_NAME:
ret_value=_keil_get_target_names(VendorWorkspaceFilename,ProjectNames,VendorProjectNames);
break;
3.8. COMPILE THE FILE !4. Modifications in the file 'projutil.e'4.1. Add a functionboolean _IsKeilProjectFilename(_str filename)
{
return(file_eq('.'get_extension(filename),KEIL_PROJECT_EXT));
}
4.2. COMPILE THE FILE !5. Changes in the file 'project.e'5.1. Associate MakefileTypeAfter the code block
if (AssociatedMakefileType==XCODE_VENDOR_NAME) {
// Xcode workspaces don't have project files, so some trickery is necessary
// to prevent having modify a whole lot of code
_ProjectSet_AssociatedFile(project_handle,strip_filename(_xmlcfg_get_filename(project_handle),'P'));
}
add
if (AssociatedMakefileType==KEIL_VENDOR_NAME) {
// KEIL workspaces don't have project files, so some trickery is necessary
// to prevent having modify a whole lot of code
//
_ProjectSet_AssociatedFile(project_handle,strip_filename(_xmlcfg_get_filename(project_handle),'P'));
}
5.2. COMPILE THE FILE !6. Changes to the 'makefile.e' file6.1. Add an entry to IniFileInfoI assume VSearch is used to find the location in the project to speed up the search for source file entries.
SourceLine is a regular expression which identifies a source file entry - the path and the source file has to be
regex tagged as group 0.
KEIL_VENDOR_NAME=>{
"VSearch"=>'### uVision2 Project, (C) Keil Software',
"VBefore"=>2,
"VFileExt"=>'uv2',
"SourceLine"=>'^File:b:n,:n,<{:p}><:p>:b0x:h:b*$',
"SourceList"=>'',
"SourceListBegin"=>'',
"SourceListEnd"=>'',
"DepListBegin"=>'',
"DepListEnd"=>'',
"VariableStart"=>'',
"VariableEnd"=>'',
"ContinuationChar"=>'',
},
6.2. Changes to the 'GetFileListFromMakefile' functionThis file extracts the source files from the custom project file and adds it to the SlickEdit workspace. Anyway
I assume the changes I have made here are quick and dirty and have not much to do with the original indention of this funciton.
So here we go - the code just corrects the MakefileName which was not set correctly at another position.
So after the code block
} else if(Type==XCODE_VENDOR_NAME) {
// Gets files from a Xcode file
if (listboxFormat) {
get_window_id(orig_view_id);
activate_window(FileListViewId);
int last_line=p_line;
activate_window(orig_view_id);
_xcode_get_file_list(MakefileName,FileListViewId,ConvertToAbsolute);
activate_window(FileListViewId);
p_line=last_line;_end_line();
search('^','R@',' ');
activate_window(orig_view_id);
} else {
_xcode_get_file_list(MakefileName,FileListViewId,ConvertToAbsolute);
}
return(0);
}
add an else if clause
else if(Type==KEIL_VENDOR_NAME) {
MakefileName = strip_filename(MakefileName,'PE') KEIL_PROJECT_EXT;
}
6.3. COMPILE THE FILE !7. Create a custom file for our project file support 'keiluv2.e'
///////////////////////////////////////////////////////////////////////////////
#pragma option(strict,on)
#include "slick.sh"
#include "cbrowser.sh"
/**
* holds the whole project file
*/
static typeless keil_idHash;
/**
* pointer to keil_idHash:['objects']
*/
static typeless *keil_objects=0;
/**
* the name of the file that is loaded in keil_idHash and
* keil_objects
*/
/**
* the name of the file that is loaded in keil_idHash and keil_objects
*/
static _str keil_project_file='';
/**
* the base directory for files with relative paths
*/
static _str keil_project_path='';
/**
* Extract Keil target names - currently just one (the first)
* target is handled.
*
* @param VendorWorkspaceFilename
* @param ProjectNames
* @param VendorProjectNames
*
* @return int
*/
int _keil_get_target_names(_str VendorWorkspaceFilename, _str (&ProjectNames)[],_str (&VendorProjectNames)[])
{
_str projectfile;
_str dummy;
keil_split_target_name(VendorWorkspaceFilename,projectfile,dummy);
//try to loacate the 'Target' entry - tag target name as $0
if (search('Target:b\({([0-9A-Za-z._ ()]#)}\)','R') != 0) {
return 1;
}
_str targets = get_text(match_length('0'),match_length('S0'));
_str vpjName = targets;
_str vpjFullName = targets;
_str target_name=targets;
if (target_name:!='') {
vpjName=VSEProjectFilename(target_name);
ProjectNames[ProjectNames._length()]=vpjName;
// since the targets/projects don't exist in their own files,
// point them all at the vpj
vpjFullName=strip_filename(VendorWorkspaceFilename,'N'):+vpjName;
// to make sure that everything goes smoothly, create a dummy file if
// it hasn't been created yet
if (file_exists(vpjFullName)) {
VendorProjectNames[VendorProjectNames._length()]=vpjFullName;
} else {
// wild crazy stuff here
// temporiarly set the Vendor Project file to the keil project file
// while the vpj file is being created, the associated file will be
// changed to be the vpj, but for now, a real file must be used
VendorProjectNames[0]=strip_filename(VendorWorkspaceFilename,'PE') ".uv2";
}
}
vpjName=VendorProjectNames[0];
ProjectNames[0]=strip_filename(VendorProjectNames[0], 'PE') ".vpj";
return 0;
}
int _keil_get_configs(_str VendorWorkspaceFilename, ProjectConfig (&configList)[])
{
_str projectfile;
_str target_name;
if (keil_split_target_name(VendorWorkspaceFilename,projectfile,target_name)) {
return -1;
}
int status=keil_maybe_open_project(projectfile);
if (status) {
return status;
}
if (file_exists(VendorWorkspaceFilename)) {
_ProjectSet_WorkingDir(_ProjectHandle(VendorWorkspaceFilename),keil_project_path);
}
return 0;
}
/**
*
* @param VendorWorkspaceFilename
* @param projectfile
* @param target
*
* @return boolean
*/
static boolean keil_split_target_name(_str VendorWorkspaceFilename, _str & projectfile, _str & target)
{
projectfile=strip_filename(VendorWorkspaceFilename,'P');
target=strip_filename(VendorWorkspaceFilename,'PE');
target=maybe_quote_filename(target);
return true; //$$GN: I'm not sure what the result shall be but returning true seems to be fine for now
}
/**
* Opens an keil project file if it is not already open and sets
* the following global variables:
* <ol>
* <li>keil_idHash</li>
* <li>keil_objects</li>
* <li>keil_project_file</li>
* <li>keil_project_path</li>
* </ol>
*
* @param filename the name of the file to open. This should be the
* project.pbxproj and not the .keil directory
*
* @return zero on success
*/
static int keil_maybe_open_project(_str filename)
{
if (file_eq(filename,keil_project_file)) {
return 0;
}
keil_close_project();
keil_project_file=filename;
// first get rid of the actual project file name
keil_project_path=strip_filename(keil_project_file,'N');
// now get rid of the '.keil' file/directory name
if (last_char(keil_project_path):==FILESEP) {
keil_project_path=substr(keil_project_path,1,length(keil_project_path)-1);
}
keil_project_path=strip_filename(keil_project_path,'N');
int temp_view_id;
int orig_view_id;
int status=_open_temp_view(filename,temp_view_id,orig_view_id);
if (status) {
keil_project_file='';
return 1;
}
top();
up();
activate_window(orig_view_id);
_delete_temp_view(temp_view_id);
return 0;
}
static void keil_close_project()
{
keil_idHash._makeempty();
keil_objects=0;
keil_project_file='';
keil_project_path='';
}
7.1. COMPILE THE FILE !8. Create a raw template for a SlickEdit project file in 'prjtemplates.vpt' <Template
Name="Keil uVision"
ShowOnMenu="0">
<Config Name="Release"
DebugCallbackName="gdb"
Type="gnuc">
<Includes>
<Include Dir="%(INCLUDE)"/>
</Includes>
<Menu>
<Target
Name="Build"
MenuCaption="&Build"
CaptureOutputWith="ProcessBuffer"
SaveOption="SaveCurrent"
RunFromDir="%rw">
<Exec CmdLine='j:\uv3\uv3 "%f"'/>
</Target>
<Target
Name="Compile"
MenuCaption="&Compile"
CaptureOutputWith="ProcessBuffer"
SaveOption="SaveCurrent"
RunFromDir="%rw">
<Exec CmdLine='cx51 "%f"'/>
</Target>
</Menu>
</Config>
<Files AutoFolders="PackageView">
</Files>
</Template>
9. Add the new feature to the [Project] menu9.1. Go to [Macro][Menus...] and open '_mdi_menu'9.2. Select the {&Project}{Open O&ther Workspace} and press the [Insert] button9.2.1. Set the menu Caption 'Keil uVision2 Project...'9.2.2. Set Command 'workspace_open_keiluv2'
Huch - finished! Now I am looking forward to get some feedback and probably also improvements
Gary