I was finally able to tell ptop to unindent at the end of the uses clause. It was a matter of specifying uses in the list of de-indents for the semicolon:
semicolon=crsupp,dindonkey,crafter
[semicolon]=if,then,else,while,with,for,colon,equals,uses
while I was mistakenly trying to specify it in the [uses] clause directly. Here is my full ptop.cfg file, if anyone is interested:
end=crbefore,dindonkey,dindent,crafter,lower
[end]=if,then,else,while,with,for,record,try,finally,except,class,object,private,public,protected,published,casevar,colon,equals
begin=crbefore,dindonkey,inbytab,crafter
[begin]=var,label,const,type
if=spaft,gobsym,inbytab,lower
then=,lower
else=crbefore,dindonkey,inbytab,lower
[else]=if,then,else
proc=dindonkey,spaft,lower
[proc]=var,label,const,type
var=blinbefore,dindonkey,spaft,inbytab,lower
[var]=var,label,const,type
of=crsupp,spbef,spaft,lower
while=spaft,gobsym,inbytab,crafter,lower
do=crsupp,spbef,lower
case=spaft,gobsym,inbytab,crafter,lower
with=spaft,gobsym,inbytab,crafter,lower
for=spaft,gobsym,inbytab,crafter,lower
repeat=inbytab,crafter,lower
until=crbefore,dindonkey,dindent,spaft,gobsym,crafter,lower
[until]=if,then,else,while,with,for,colon,equals
func=dindonkey,spaft,lower
[func]=var,label,const,type
label=blinbefore,spaft,inbytab,lower
const=blinbefore,dindonkey,spaft,inbytab,lower
[const]=var,label,const,type
type=blinbefore,dindonkey,spaft,inbytab,lower
[type]=var,label,const,type
record=inbyindent,crafter,lower
[record]=end
string=
prog=blinbefore,spaft,lower
asm=lower
try=crbefore,inbytab,crafter,lower
finally=crbefore,dindent,inbytab,crafter,lower
[finally]=try
except=crbefore,dindent,inbytab,crafter,lower
[except]=try
raise=lower
class=inbyindent,lower
object=inbyindent,lower
constructor=lower
destructor=lower
inherited=lower
property=lower
private=crbefore,dindonkey,spaft,inbytab,lower
[private]=end,private,public,protected,published
public=crbefore,dindonkey,spaft,inbytab,lower
[public]=end,private,public,protected,published
protected=crbefore,dindonkey,spaft,inbytab,lower
[protected]=end,private,public,protected,published
published=crbefore,dindonkey,spaft,inbytab,lower
[published]=end,private,public,protected,published
initialization=lower
finalization=lower
inline=lower
library=blinbefore,spaft,lower
interface=blinbefore,crafter,lower
implementation=blinbefore,dindonkey,crafter,lower
[implementation]=end,var,label,const,type,property
read=lower
write=lower
unit=blinbefore,spaft,lower
and=lower
arr=lower
div=lower
down=lower
file=lower
goto=lower
in=lower
mod=lower
not=lower
nil=lower
or=lower
set=lower
to=lower
virtual=lower
uses=blinbefore,crafter,spaft,inbytab,lower
casevar=spaft,gobsym,inbytab,crafter
ofobject=
becomes=spbef,spaft,gobsym
notequal=
lessorequal=
greaterorequal=
delphicomment=crafter
dopencomment=
dclosecomment=
opencomment=crsupp
closecomment=crsupp
semicolon=crsupp,dindonkey,crafter
[semicolon]=if,then,else,while,with,for,colon,equals,uses
colon=inbytab
equals=spbef,spaft,inbytab
openparen=gobsym
closeparen=
period=crsupp
endoffile=
other=
There is still the problem of forward declarations, but I think I can live with it.
Note: I changed a bit the configuration file to output all keywords in lowercase, so that Emacs' opascal-mode can highlight them correctly. (Don't know why this mode enforces exact case matches when Pascal is case-insensitive. Oh, well.)