/**
* @change Added the ability to extract code from included files
* - Sandoz, 2002.
*/
#include <creator.h>
#define WIZ WIZ_PRESENT
#define EXTRACT_CODE 1
#define LINE_NUMBERS 2
inherit COMMAND_BASE;
/** @ignore yes */
string *get_includes( string file, string file_name ) {
string *includes, *lines, line, name, *bits, stuff;
int i;
lines = ({ });
foreach( line in explode( file, "\n") )
if( line[0..8] == "#include ")
lines += ({ line[9..] });
includes = ({ });
foreach( line in lines ) {
if( line[0] == '\"' ) {
bits = explode( file_name, "/");
sscanf( line, "\"%s\"", name );
stuff = read_file( implode( bits[0..<2], "/")+"/"+name );
if( stuff )
includes += ({ "/"+implode( bits[0..<2], "/")+"/"+name });
} else if( line[0] == '<') {
sscanf( line, "<%s>", name );
}
if( name[0] == '/' ) {
stuff = read_file( name );
if( stuff )
includes += ({ name });
}
bits = master()->define_include_dirs();
while( !stuff && i < sizeof(bits) ) {
stuff = read_file( sprintf( bits[i], name ) );
if( stuff )
includes += ({ sprintf( bits[i], name ) });
i++;
}
}
return includes;
} /* get_includes() */
/** @ignore yes */
mixed extract_code( string thing, mixed fnd, int inc, int num ) {
string str, func, ping, file, *includes, bit;
int i, startline, j;
mixed tmp;
ping = ( !inc ? fnd[1] : fnd[1]+".c");
func = fnd[0];
if( !file_exists(ping) )
return notify_fail("The file for "+thing+" doesn't exist.\n");
file = read_file(ping);
if( !strlen(file) )
return notify_fail("Could not read file.\n");
tmp = reg_assoc( file, ({"\n[a-z_ \t]*[\\* ][ \t]*"+func+
"[ \t]*\\([a-zA-Z0-9, _\\*\n\t]*(...)?[ \t]*\\)[ \t\n]*{",
"\n}" }), ({ 1, 2 }) );
while( tmp[1][j] != 1 ) {
j++;
// Must be an included function.
if( j == sizeof(tmp[1]) ) {
if( inc ) {
includes = get_includes( file, fnd[1] );
if( sizeof(includes) ) {
foreach( bit in includes )
if( str = extract_code( bit, ({ func, bit }), 0, num ) )
return str;
}
}
return notify_fail("Could not extract code from an "
"included function.\n");
}
}
if( num )
startline = sizeof( explode( implode( tmp[0][0..j], ""),
"\n") );
j++;
str = "";
if( !inc )
str += "*** Extracted from "+ping+"\n";
while( tmp[0][j][i] != '\n' ) {
if( tmp[0][j][i] == '}' ) {
tmp = tmp[0][j - 1][1..] + tmp[0][j][0..i];
if( num )
tmp = implode( explode( tmp, "\n"),
(: ({ $1[0]+1, $1[1]+"\n"+$1[0]+" "+$2 }) :),
({ startline, ""}) )[1];
return ( tmp[0] == '\n' ? tmp[1..] : tmp );
}
i++;
}
tmp = implode( tmp[0][j-1..j+1], "");
if( num )
tmp = implode( explode( tmp, "\n"),
(: ({ $1[0]+1, $1[1]+"\n"+$1[0]+" "+$2 }) :),
({ startline, ""}) )[1];
str += ( tmp[0] == '\n' ? tmp[1..] : tmp );
return str;
} /* extract_code() */
/** @ignore yes */
int cmd( string str ) {
string tmp, func, thing, s, ping;
object ob, *obs, fish;
mixed fnd;
int flags;
notify_fail("Usage: find [-d] [-n] function() <object(s)>\n");
if( !str )
return 0;
while( sscanf( str, "-%s %s", s, str ) == 2 )
switch( s ) {
case "d":
flags |= EXTRACT_CODE;
break;
case "n":
flags |= (LINE_NUMBERS | EXTRACT_CODE);
break;
default:
return notify_fail("Unknown option '"+s+"'.\n");
}
if( sscanf( str, "%s() %s", func, thing ) != 2 &&
sscanf( str, "%s %s", func, thing ) != 2 )
return 0;
obs = WIZ->wiz_present( thing, TP );
if( !sizeof(obs) )
return notify_fail("Can't find "+thing+".\n");
s = "";
fnd = ({ });
foreach( ob in obs ) {
if( ping = function_exists( func, ob, 1 ) ) {
s += "*** "+WIZ->desc_object(ob)+": "+
func+"() found in "+ping+"\n";
fnd += ({ func, ping });
} else {
s += "*** "+WIZ->desc_object(ob)+": "+
func+"() not found.\n";
}
fish = ob;
while( fish = shadow( fish, 0 ) )
if( function_exists( func, fish, 1 ) ) {
s += " Shadowed by "+file_name(fish)+"\n";
fnd += ({ func, base_name(fish) });
}
}
/*
* If we are going to extract a function, there are many different
* possible formats it might be declared in:
* void foo*(*)*{
* Take * as indicating where whitespace might split the header,
* whitespace possibly being a space, a tab or a new line.
*/
if( ( flags & EXTRACT_CODE ) && sizeof(fnd) ) {
if( sizeof(fnd) > 2 )
s += "Can only extract code from one object at a time.\n";
else if( !tmp = extract_code( thing, fnd, 1,
( flags & LINE_NUMBERS ) ) )
return 0;
s += tmp;
}
TP->more_string(s);
return 1;
} /* cmd() */