From 56c373e592fbd6d544b04694840c094f4b5102ff Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Tue, 13 Apr 1999 02:06:36 +0000 Subject: [PATCH] Rewrote the doc-features program in Perl. This program scan the C-sources of the library and all kernel modules and outputs everything it can find about all features. To do: sort features and add command-line parameters, implement slightly better layout. The perl program completely replaces the C program and already has much more functionality. This program will be very helpful to write the kernel module documentation, and especially to keep it up-to-date: as the C sources are examined, updates need only be done at one place, in the source code. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@384 7894878c-1315-0410-8ee3-d5d059ff63e0 --- prog/doc/Module.mk | 41 ------- prog/doc/doc-features.c | 148 ----------------------- prog/doc/doc-features.pl | 254 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 189 deletions(-) delete mode 100644 prog/doc/Module.mk delete mode 100644 prog/doc/doc-features.c create mode 100755 prog/doc/doc-features.pl diff --git a/prog/doc/Module.mk b/prog/doc/Module.mk deleted file mode 100644 index 6d89dfad..00000000 --- a/prog/doc/Module.mk +++ /dev/null @@ -1,41 +0,0 @@ -# Module.mk - Makefile for a Linux module for reading sensor data. -# Copyright (c) 1998, 1999 Frodo Looijaard -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -# Note that MODULE_DIR (the directory in which this file resides) is a -# 'simply expanded variable'. That means that its value is substituted -# verbatim in the rules, until it is redefined. -MODULE_DIR := prog/doc - -# Regrettably, even 'simply expanded variables' will not put their currently -# defined value verbatim into the command-list of rules... -PROGDOCTARGETS := $(MODULE_DIR)/doc-features -PROGDOCSOURCES := $(MODULE_DIR)/doc-features.c - -# Include all dependency files. We use '.rd' to indicate this will create -# executables. -INCLUDEFILES += $(PROGDOCSOURCES:.c=.rd) - -$(PROGDOCTARGETS): $(PROGDOCSOURCES:.c=.ro) lib/$(LIBSHBASENAME) - $(CC) -o $@ $(PROGDOCSOURCES:.c=.ro) -Llib -lsensors - -all-prog-doc: $(PROGDOCTARGETS) -all :: all-prog-doc - -clean-prog-doc: - $(RM) $(PROGDOCSOURCES:.c=.rd) $(PROGDOCSOURCES:.c=.ro) \ - $(PROGDOCTARGETS) -clean :: clean-prog-doc diff --git a/prog/doc/doc-features.c b/prog/doc/doc-features.c deleted file mode 100644 index 86828abb..00000000 --- a/prog/doc/doc-features.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - doc-features.c - A program to dump sensor feature documentation - Copyright (c) 1998, 1999 Frodo Looijaard - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This program uses undocumented sensors library access. It it undocumented - for a reason: normal programs really should not work on this level! */ - -#include "lib/data.h" -#include -#include - -const char *lookup_feature_name(int featurenr, - const sensors_chip_features *chipdata) -{ - int i; - if (featurenr == SENSORS_NO_MAPPING) - return ""; - for (i = 0; chipdata->feature[i].name ; i++) - if (chipdata->feature[i].number == featurenr) - return chipdata->feature[i].name; - return "***ERROR***"; -} - -const char *mode_string(int mode) -{ - if (mode == SENSORS_MODE_RW) - return "RW"; - else if (mode == SENSORS_MODE_R) - return "R "; - else if (mode == SENSORS_MODE_W) - return " W"; - else - return "--"; -} - -void dump_feature(const sensors_chip_feature *featuredata, - const sensors_chip_features *chipdata) -{ - printf(" %17s: %17s %17s %2s\n",featuredata->name, - lookup_feature_name(featuredata->logical_mapping,chipdata), - lookup_feature_name(featuredata->compute_mapping,chipdata), - mode_string(featuredata->mode)); -} - -int qsort_compare (const void *f1, const void *f2) -{ - return strcmp((* ((sensors_chip_feature * const *)f1))->name, - (* ((sensors_chip_feature * const *)f2))->name); -} - -void dump_chip (const sensors_chip_features *chipdata) -{ - int i; - sensors_chip_feature **features; - for (i = 0; chipdata->feature[i].name; i++); - - features = malloc(sizeof(*features) * i+1); - for (i = 0; chipdata->feature[i].name; i++) - features[i] = chipdata->feature + i; - features[i] = chipdata->feature + i; - qsort(features,i,sizeof(*features),qsort_compare); - - printf("Chip `%s'\n",chipdata->prefix); - printf(" %17s %17s %17s %2s\n","NAME","LABEL CLASS","COMPUTE CLASS", - "RW"); - for (i = 0; features[i]->name; i++) - dump_feature(features[i],chipdata); - - free(features); - printf("\n"); -} - -void print_short_help(void) -{ - fprintf(stderr,"Usage: doc-features [-h] [-v] [chipname]..\n"); - fprintf(stderr,"Try `doc-features -h' for more information\n"); -} - -void print_long_help(void) -{ - fprintf(stderr,"Usage: doc-features [-h] [-v] [chipname]..\n"); - fprintf(stderr," -h, --help Display this help text\n"); - fprintf(stderr," -v, --version Display version information\n"); - fprintf(stderr,"If no chipnames are specified, information for all chips is dumped.\n"); -} - -void print_version(void) -{ - printf("doc-features version 1.0\n"); -} - -int main (int argc, char *argv[]) -{ - int c,i; - - struct option long_opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v'} - }; - - while(1) { - c = getopt_long(argc,argv,"hv",long_opts,NULL); - if (c == EOF) - break; - switch(c) { - case ':': - case '?': - print_short_help(); - exit(1); - case 'h': - print_long_help(); - exit(0); - case 'v': - print_version(); - exit(0); - default: - fprintf(stderr,"Internal error while parsing options!\n"); - exit(1); - } - } - - if (optind == argc) - for (i = 0; sensors_chip_features_list[i].prefix ; i++) - dump_chip(sensors_chip_features_list+i); - else - for (; optind != argc ; optind ++) - for (i = 0; sensors_chip_features_list[i].prefix; i++) - if (!strcmp(sensors_chip_features_list[i].prefix,argv[optind])) - dump_chip(sensors_chip_features_list+i); - - return 0; -} - diff --git a/prog/doc/doc-features.pl b/prog/doc/doc-features.pl new file mode 100755 index 00000000..d04bb5e5 --- /dev/null +++ b/prog/doc/doc-features.pl @@ -0,0 +1,254 @@ +#!/usr/bin/perl + +use strict; + +# Features is a hash of references (indexed by SENSORS_*_PREFIX names) to +# a hash with these elements: +# prefix: The prefix name +# arrayname: The name of the c-array containing its data +# features: A reference to an array of references to hashes, each +# containing the following fields: +# number: The preprocessor symbol for the number of this feature +# name: The name of this feature +# logical_mapping: The preprocessor symbol for the logical mapping +# feature +# compute_mapping: The preprocessor symbol for the compute mapping +# feature +# mode_read: 1 if the feature is readable, 0 if not +# mode_write: 1 if the feature is writable, 0 if not +# sysctl: Preprocessor name of the sysctl file +# offset: Offset (in longs) within the sysctl file +# magnitude: Magnitude of this feature + +use vars qw(%features %sysctls %feature_name); + +# Scan chips.h to get all prefix values +# Store the results in features{...}->prefix +# $_[0]: Name of chips.h file +sub scan_chips_h +{ + my ($chips_h) = @_; + my ($def,$val); + open INPUTFILE,$chips_h or die "Can't open $chips_h!"; + while () { + $features{$def}->{prefix} = $val + if ($def,$val) = /^\s*#\s*define\s+(SENSORS_\w+_PREFIX)\s+"(\S+)"/; + + } + close INPUTFILE; +} + +# Scan chips.c to get the features names +# Store the results in features{...}->arrayname +# $_[0]: Name of the chips.c file +sub scan_chips_c_1 +{ + my ($chips_c) = @_; + my ($def,$val); + open INPUTFILE,$chips_c or die "Can't open $chips_c!"; + while ( !~ /^\s*sensors_chip_features/ ) {}; + while () { + last if /^\s*{\s*0/; + $features{$def}->{arrayname} = $val + if ($def,$val) = /^\s*{\s*(SENSORS_\w+_PREFIX)\s*,\s*(\w+)\s*}\s*,\s*$/; + } + close INPUTFILE; +} + +# $_[0]: line to tokenize +# Returns the list of tokens +# Tokens are either '{', '}', ',', ';' or anything between them. Spaces on +# each side of a token are removed; spaces inside a token are not. +sub tokenize +{ + my ($line) = @_; + my (@res,$next); + @res = (); + $line =~ s/^\s*//; + while (length $line) { + if ($line =~ s/^\s*$//) { + last; + } elsif ($line =~ s/^{\s*//) { + push @res, '{'; + } elsif ($line =~ s/^}\s*//) { + push @res, '}'; + } elsif ($line =~ s/^;\s*//) { + push @res, ';'; + } elsif ($line =~ s/^,\s*//) { + push @res, ','; + } else { + ($next) = $line =~ /^(\S+?)(?=[{},;\s])\s*/; + $line =~ s/^(\S+?)(?=[{},;\s])\s*//; + push @res, $next; + } + } + return @res; +} + +# $_[0]: File to read from +# $_[1]: Feature to write to +sub scan_chip_c_entry +{ + my ($file,$feature) = @_; + my ($line,@tokens,$next,$new); + for (;;) { + $line = <$file>; + @tokens = (@tokens,tokenize($line)); + last if $line =~ /;/; + } + die "Parse error: initial '{' expected for $feature->arrayname" + if shift @tokens ne '{'; + $feature->{features} = []; + while (shift @tokens eq '{') { + $new = {}; + $new->{number} = shift @tokens; + last if $new->{number} eq "0"; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $next = shift @tokens; + ($new->{name}) = $next =~ /^"(.*)"$/; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $new->{logical_mapping} = shift @tokens; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $new->{compute_mapping} = shift @tokens; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $next = shift @tokens; + $new->{mode_read} = ($next eq "SENSORS_MODE_R" or + $next eq "SENSORS_MODE_RW")?1:0; + $new->{mode_write} = ($next eq "SENSORS_MODE_W" or + $next eq "SENSORS_MODE_RW")?1:0; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $new->{sysctl} = shift @tokens; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $next = shift @tokens; + ($new->{offset}) = $next =~ /^VALUE\s*\((\d+)\s*\)/ + or die "Parse error: 'VALUE(..)' expected for $feature->arrayname"; + die "Parse error: ',' expected for $feature->arrayname" + if shift @tokens ne ','; + $new->{magnitude} = shift @tokens; + $next = shift @tokens; + $next = shift @tokens if $next eq ','; + push @{$feature->{features}},$new; + $feature_name{$new->{number}} = $new->{name}; + die "Parse error: '}' expected for $feature->arrayname" if $next ne '}'; + shift @tokens; + + } +} + +# Scan chips.c to get the features names +# Store the results in features{...}->feature +# $_[0]: Name of the chips.c file +sub scan_chips_c_2 +{ + my ($chips_c) = @_; + my ($line,$name,$el,$feature); + open INPUTFILE,$chips_c or die "Can't open $chips_c!"; + while ($line = ) { + next if $line !~ /sensors_chip_feature /; + ($name) = $line =~ /sensors_chip_feature\s*(\w+)\s*\[/; + foreach $el (keys %features) { + $feature = $features{$el}; + last if $feature->{arrayname} eq $name + } + die "Can't find feature belonging to $name!" if (! defined $feature); + scan_chip_c_entry \*INPUTFILE,$feature; + } +} + +# $_[0]: Name of the kernels module +sub scan_kernel_module +{ + my ($module_name) = @_; + my ($line,@tokens,$val,$name); + open INPUTFILE,$module_name or die "Can't open $module_name!"; + while ($line = ) { + next if $line !~ /^\s*static\s*ctl_table/; + @tokens = (); + for (;;) { + $line = ; + @tokens = (@tokens,tokenize($line)); + last if $line =~ /;/; + } + while (@tokens) { + for (;;) { + $val = shift @tokens; + last if $val ne '{'; + } + last if $val eq "0"; + die "Parse error: ',' expected within $module_name" + if shift @tokens ne ','; + $name = shift @tokens; + ($sysctls{$val}) = $name =~ /^"(\S+)"$/; + for (;;) { + last if shift @tokens eq '{'; + } + } + } + close INPUTFILE; +} + +# $_[0]: Base directory +sub scan_all +{ + my ($prefix) = @_; + my ($filename); + scan_chips_h $prefix . "/lib/chips.h"; + scan_chips_c_1 $prefix . "/lib/chips.c"; + scan_chips_c_2 $prefix . "/lib/chips.c"; + foreach $filename (glob ($prefix ."/kernel/chips/*.c")) { + scan_kernel_module $filename + } +} + +# $_[0]: index in master hash +sub output_data +{ + my ($index) = @_; + my ($feature,$data,$read_write); + $feature = $features{$index}; + printf "Chip `%s'\n",$feature->{prefix}; + print " LABEL LABEL CLASS COMPUTE CLASS ACCESS MAGNITUDE\n"; + foreach $data (@{$feature->{features}}) { + $read_write = $data->{mode_read} + 2 * $data->{mode_write}; + if ($read_write == 0) { + $read_write = "--"; + } elsif ($read_write == 1) { + $read_write = "R "; + } elsif ($read_write == 2) { + $read_write = " W"; + } else { + $read_write = "RW"; + } + printf "%15s %15s %15s %2s %2s\n", + $data->{name}, $feature_name{$data->{logical_mapping}}, + $feature_name{$data->{compute_mapping}}, + $read_write,$data->{magnitude}; + } + print "\n"; + print " LABEL FEATURE SYMBOL ". + "SYSCTL FILE:OFFSET\n"; + foreach $data (@{$feature->{features}}) { + printf "%15s %40s %15s:%1d\n",$data->{name}, $data->{number}, + $sysctls{$data->{sysctl}}, $data->{offset}, $data->{magnitude}; + } +} + +sub initialize +{ + $feature_name{SENSORS_NO_MAPPING} = "NONE"; +} + + +initialize; +scan_all "../.."; +my $el; +foreach $el (keys %features) { + output_data $el; + print "\n\n"; +}