#!/usr/bin/perl # # IndexListing.pl -- Chris B. Sears # # December 19, 1999 # # The Linux Core Kernel Commentary didn't have an index. # This script takes the listing file and the source tree # and using commonly found household text editing utitilies # constructs a thorough cross reference. # # The result is index.pdf # # This script uses: # Exhuberant CTags: # rpmfind.net/linux/RPM/ctags.html # GNU enscript # GhostScript ps2pdf # $max_references = 10; %file_offsets = (); $offset = 0; use Text::Wrap; $Text::Wrap::columns = 50; sub index_file { open (INDEX_OUT, ">" . $_[0]); open (INDEX_IN, "index_data"); $entry = ""; while ($line = ) { $output = ""; @words = split(" ", $line); # #skip over gcc cruft # if (($words[0] eq "__initfunc") || ($words[0] eq "EXPORT_SYMBOL")) { next; } # # skip duplicate names # if ($words[0] eq $entry) { next; } $entry = $words[0]; # # merge multiple definition and prototype line numbers. # for functions and prototypes use two passes # sort functions before prototypes # $count = 0; @defs = (); if ($_[0] eq "index_f") { open (INDEX_COPY, "index_data"); while ($line = ) { @copies_words = split(" ", $line); if (($copies_words[0] eq $entry) && ($copies_words[1] eq "function")) { $defs[$count] = ($file_offsets{$copies_words[3]} + $copies_words[2]); $count++; } } close (INDEX_COPY); open (INDEX_COPY, "index_data"); while ($line = ) { @copies_words = split(" ", $line); if (($copies_words[0] eq $entry) && ($copies_words[1] eq "prototype")) { $defs[$count] = ($file_offsets{$copies_words[3]} + $copies_words[2]); $count++; } } close (INDEX_COPY); } else { open (INDEX_COPY, "index_data"); while ($line = ) { @copies_words = split(" ", $line); if ($copies_words[0] eq $entry) { $defs[$count] = ($file_offsets{$copies_words[3]} + $copies_words[2]); $count++; } } close (INDEX_COPY); } # # Find references to the names # $output = $output . $words[0] . " -"; for ($i = 0; $i < $count; $i++) { $output = $output . " " . $defs[$i]; } $output = $output . " -"; system("grep -n " . "'\\<" . $words[0] . "\\>'" . " arch/*/*/* fs/* include/*/* init/*" . " ipc/* kernel/* mm/* >index_tmp"); open (INDEX_TMP, "index_tmp"); $total = 0; OUTER: while ($line = ) { @match_words = split(":", $line); $offset = ($file_offsets{$match_words[0]} + $match_words[1]); # # but filter out the definitions # for ($i = 0; $i < $count; $i++) { if ($defs[$i] == $offset) { next OUTER; } } # # and limit the total number of references # $total++; if ($total <= $max_references) { $output = $output . " " . $offset; } } if ($total > $max_references) { $output = $output . sprintf " [+%d]", $total - $max_references; } close (INDEX_TMP); system("rm -f index_tmp"); if (substr($output, -2, 2) eq " -") { chop $output; chop $output; } @output_line = ($output); print INDEX_OUT wrap("", " ", @output_line), "\n"; } close (INDEX_OUT); close (INDEX_IN); system("enscript -r " . $_[0] . " --columns=3 -o " . $_[0] . ".ps -j -b \"Linux Core Kernel Commentary -- " . $_[1] . "\" -f Courier8 -F Helvetica10"); system("rm -f index_data " . $_[0]); } # # scan lckc_code for FILE: # create a list of names and offsets # open (LISTING, "lckc_code"); while ($line = ) { if ($line =~ / FILE:/) { @words = split(" ", $line); $file_offsets{$words[2]} = $offset; } else { $offset++; } } close (LISTING); system("ctags -xR --c-types=fp" . " arch fs include init ipc kernel mm >index_data"); system("sort -df index_data >sort_tmp; mv sort_tmp index_data"); index_file("index_f", "Functions"); system("ctags -xR --c-types=dvegstu" . " arch fs include init ipc kernel mm | grep -v \"undef\" >index_data"); system("sort -df index_data >sort_tmp; mv sort_tmp index_data"); index_file("index_d", "Macros, Variables, Enumerations, Structures, Typedefs and Unions"); system("cat index_f.ps index_d.ps >index.ps"); system("ps2pdf index.ps"); system("rm -f index.ps index_f.ps index_d.ps");