Using GNU Pascal (GPC) with BBEdit on Mac OS X Tiger
Peter N Lewis, Stairways Software



Using GNU Pascal (GPC) with BBEdit
on Mac OS X Tiger
by Peter N. Lewis
Posted: 11/1/05

Having been more or less forced to move from CodeWarrior Metrowerks Pascal, we chose GNU Pascal, initially a small project and then an entire application. At the time, Free Pascal was not available, so now Pascal users have two choices, both with their own pros and cons.

Regardless, the obvious new development environment is XCode, but XCode currently (as of 2.1) has very poor support for non-natively handled compilers. It's rule handling for individual files is ok, but there is no control over linking and no way of specifying dependencies. Also, XCode has many of its own problems, including complexity and performance, and its one shining point (as far as developing in Pascal goes) is the GUI for debugging, but this is heavily marred by gdb's poor support for debugging Pascal (including frequent crashes and limited variable display types).

Another choice is BBEdit. Steller performance as a text editor is its hallmark, and with shell worksheets, text factories, integrated AppleScript and Unix tool support, and excellent Subversion/CVS support, it beats XCode in many ways. It's primary limitations for developing in Pascal include

  1. no inbuilt build system
  2. no compiler with error messages
  3. no ability to go directly to where a procedure is defined
  4. no concept of a "project"
  5. no debugger
  6. limited syntax coloring (it colors only keywords)


This document describes how the first three can be addressed, and touches on the remaining.

Contents



Install GPC


The first step is to install GPC, either from
source, or from the binary package, as well as the Mac OS X Pascal Interfaces for GNU Pascal. While you are at it, install the Xcode integration Kit.

Create the Project


Ok, so BBEdit does not really have a concept of a project, and so has no fancy templates and what have you, so we'll use XCode and Adriaan van Osí templates. Launch XCode, crate a new project, select GNU Pascal (Makefile), Carbon Application Package nib (or probable any other project, but that will be used for this example), and create the project, call it, for example, XCodeApp. If you call it something different, change the text below as appropriate.

Build in XCode now to ensure it works as expected in XCode.

Now, this is not a tutorial about writing Mac applications or Makefiles, it is a tutorial about making projects work neatly in BBEdit. So we'll use Adriaan's very nice Makefile, but we'll make (sorry for the pun!) it work under BBEdit. You do not need to understand any of this really, unless something goes wrong (and what could possibly go wrong?).

In XCode, choose Edit Active Target, switch to Custom Build Settings, and select all the settings, and Copy. Open the Makefile, and near the top, add:

## BBEdit section
ifdef BBEdit
SRCROOT = $(PWD)
SYSTEM_DEVELOPER_TOOLS = /Developer/Tools

[PASTED ITEMS]
endif


Remove the quotes from GPC_WARNINGS ("-W -Wall"). Close and save.

Create a BBEdit Shell Worksheet


In BBEdit, choose New -> Shell Worksheet, and select /bin/tcsh. You can use another shell, with a few minor changes, but I'll be assuming you are using tcsh.

In the Worksheet, type:

cd ~/XCodeApp
setenv BBEDIT 1
make _application_pack


(change the cd to match your project directory). Select All, and Press Enter (not Return!) to execute it. Your project should build cleanly. You can type:

build/Debug/XCodeAppDebug.app/Contents/MacOS/XCodeAppDebug[Press Enter]


to run your newly build application.

Save your Worksheet to Compile.worksheet in your XCodeApp project directory.

Create the BBEdit AppleScripts


Open the BBEdit Scripts folder (BBEdit -> Scripts -> Open Scripts Folder), Open Script Editor (BBEdit -> Scripts -> Open Script Editor), and create the following AppleScript:

set theWorksheet to posix file "/Users/peter/XCodeApp/Compile.worksheet"
tell application "BBEdit"
	activate
	open theWorksheet
	set contents of window 1 to "cd ~/XCodeApp" & return ¬
		& "setenv BBEDIT 1" & return ¬
		& "make _application_pack" & return
	select text of window 1
end tell
tell application "System Events"
	tell process "BBEdit"
		key code 76 using command
	end tell
end tell


Change the path in the first line to match your project directory. Save that script as "Make Application" in the BBEdit Scripts folder.

Open the Scripts Palette (Window -> Palettes -> Scripts), and select the Make Application script, click Set Key and give it Command-M as the command key.

Press Command-M and watch your project built in BBEdit.

Repeat the above to create "Run Application", changing the "make _application_pack" to "make _application_pack && ~/XCodeApp/build/Debug/XCodeAppDebug.app/Contents/MacOS/XCodeAppDebug". Give it command-R as a command key.

That is number 1 from the list.

Compile and display errors


While developing, we often want to compile just the file we are working on, and it occasionally has a few errors that the compiler picks up. To handle compiling a single file, first add a compile_file to the Makefile. The compile_tool entry in the Makefile looks something like this:

.PHONY : compile_tool
compile_tool:
	$(MakeTargetDir)
	$(MakeBuildDir)
	$(PBuildTool) PC=$(PCompiler) CC=$(CCompiler) $(PathOptions) $(CompileOptions) $(LinkLibs) $(LinkOptions) -o "$(CompilerOutput)" "$(MainProgramFile)"


Duplicate it and change compile_tool to compile_file (twice), remove the LinkLibs and LinkOptions -o "$(CompilerOutput)" and MainProgramFile components, and add -c "$(COMPILEFILE)", to get something like this:

.PHONY : compile_file
compile_file:
	$(MakeTargetDir)
	$(MakeBuildDir)
	$(PBuildTool) PC=$(PCompiler) CC=$(CCompiler) $(PathOptions) $(CompileOptions) -c "$(COMPILEFILE)"


It is important that the compile has exactly the same options as the normal full build (otherwise gp will cheerfully rebuild everything due to the option mismatch) except that it should not have any link related options, since we are just linking.

We can test this out now by opening the Compile.worksheet, and Select All, delete, and insert the following text:

cd ~/XCodeApp
setenv BBEDIT 1
setenv COMPILEFILE "/Users/peter/XCodeApp/Sources/MainProgram.pas"
make compile_file


Select All, Enter.

As before, create an AppleScript called "Compile File" and give it command key command-K.

tell application "BBEdit"
	set thefile to file of window 1
end tell
set p to POSIX path of thefile
tell application "BBEdit"
	activate
	set w to (every window whose name is "Compile Results")
	close w
	set wind to open posix file "/Users/peter/XCodeApp/Compile.worksheet"
	set contents of wind to "cd ~/XCodeApp" & return ¬
		& "setenv COMPILEFILE " & p & return ¬
		& "make compile_file " & return ¬
		& "/usr/bin/perl ~/perl/ProcessCompileFileErrors.pl" & return
	select text of window 1
end tell
tell application "System Events"
	tell process "BBEdit"
		key code 76 using command
	end tell
end tell


Save the following perl script as ProcessCompileFileErrors.pl in ~/perl/ProcessCompileFileErrors.pl or wherever you would like to put it. I believe the Mac::OSA::Simple module comes installed in Tiger, otherwise you will need to install it.

#!/usr/bin/perl -w

use warnings;
use strict;
use diagnostics;

use utf8;
use Encode;

use Mac::OSA::Simple qw ( applescript );

our $data = applescript( <<'EOM' );
tell application "BBEdit"
	set errors to contents of window 1
end tell
EOM
$data =~ s!\r!\n!g;
$data =~ s!\A"!!;
$data =~ s!"\Z!!;
$data =~ s!\\"!"!g;
my @entries = ();
foreach ( split( /\n/, $data ) ) {
	chomp;
	next unless m!^(/Users/\w+/[A-Za-z0-9/.]*):(?:(\d+):)? (.*)!;
	my $file = $1;
	my $line = $2 || 0;
	my $message = $3;
	my $kind;
	if ( $message eq 'error:  (Each undeclared identifier is reported only once' ) {
		$message = 'Each undeclared identifier is reported only once for each routine it appears in.';
		$kind = 'note_kind';
	} elsif ( $message eq 'error:  for each routine it appears in.)' ) {
		next;
	} elsif ( $message eq 'error:  previous declaration' ) {
		$message = "   previous declaration";
		$kind = 'note_kind';
	} elsif ( $message eq 'error:  routine declaration' ) {
		$message = "   routine declaration";
		$kind = 'note_kind';
	} elsif ( $message =~ s!^error: !! ) {
		$kind = 'error_kind';
	} elsif ( $message =~ s!^warning: !! ) {
		$kind = 'warning_kind';
	} else {
		$kind = 'note_kind';
	}
	$message =~ s!"!'!g;
	push @entries, qq({result_kind:$kind, result_file:alias (posix file "$file"), result_line:$line, message:"$message"});
}
if ( @entries ) {
	my $result = applescript( <<EOM );
	tell application "BBEdit"
		make new results browser with properties {name:"Compile Results"} with data {@{[join( ",", @entries )]}}
	end tell
EOM
}


Open the MainProgram.pas file, add a syntax error, and press Command-K to compile and get a lovely browser window showing the errors.

That is item number 2 we can tick off now.

Add support for tags


BBEdit has support for exuberant ctags, which has some support for Pascal. We can take advantage of that by adding generating a tags file in our Makefile and then command-double-click will find procedures and functions in our Pascal code.

Add the following to your Makefile:

.PHONY: tags
tags:
	/Applications/BBEdit.app/Contents/Resources/ctags --excmd=number \
	   --tag-relative=no --fields=+a+m+n+S -f tags \
	   --exclude="*/GPCMacOSAll.pas" Sources/* /Developer/Pascal/GPCPInterfaces/*


You will need to periodically run "make tags" to rebuild your tags whenever you make any noticable changes to your project. The tags include all the system interfaces, so you can command double click on ShowWindow for example to see its definition. Note that you will need to be editing a file inside your project directory in order to find the tags file, as BBEdit will look in any parent folders for the tags file.

That is item number 3 we can tick off now.

A concept of "project"


Unfortunately, BBEdit has no concept of project. The closest it comes is a File Group, but File Groups have no scripting interface. Better support for scripting File Groups has been logged as a feature request with Bare Bones.

Also, the scripts described above have the project path hardcoded in them. Since I generally only work on one project at a time, this has not been a major problem for me, so I have not yet coded a solution. If File Groups worked well, I would be tempted to automatically build File Groups based on the project, and then use the fact that a File Group is open as the concept of "project" in BBEdit. Otherwise, the "current project" path could be stored in a file somewhere like ~/.currentproject and the scripts could base there paths on that. Perhaps if there is enough interest in this article, I'll expand this later.

Debugger support


GDB can be used manually, with a command like

gdb ~/XCodeApp/build/Debug/XCodeAppDebug.app/Contents/MacOS/XCodeAppDebug


in the Terminal. I have found this works poorly at best. GDB does not understand many Pascal types and is prone to crashing when it does not understant the stack frames.

GDB can also be used within the XCode GUI, so you can use XCode just for debugging.

There may be other GDB GUIs, but I have not found any that looked worth looking at, and any debugger would likely be hamstrung by working through GDB.

In the end, WriteLn debugging, which outputs into the BBEdit worksheet, generally works reasonably well, but clearly none of these solutions are ideal.

Limited Syntax Coloring


BBEdit has syntax coloring for Pascal, but it is limted to just keyword coloring. Ideally, BBEdit would have the ability to syntax color based on the tags file. This feature request has been logged with Bare Bones.

Files


The examples of the three AppleScripts, Perl script, and the finished Makefile are available from
this site.

Conclusion


Although BBEdit is not really designed as a Pascal IDE, its extendability allows it to come pretty close. While XCode is a viable alternative to this, XCode carries a lot of baggage and complexity, and its environment is much less pleasant to use than BBEdit. With these simple scripts, you can compile Pascal while retaining the pleasant BBEdit environment, and until XCode improves its sluggish editor as well as integration with non-bundled languages, BBEdit will remain a very plausible alternative.

The scripts included with this article are placed in the Public Domain
The GNU Pascal Xcode integration kit is by Adriaan van Os, and the included Makefile is licensed as "Use and edit this file as you like, but at your own risk"



Copyright © 2005, Peter N Lewis