#!/usr/bin/perl

#
# quick scanner for possible obsolete format
# for the designated initializers
#

use strict;

die "No starting directory given!\n" unless (@ARGV);

my $startdir = shift(@ARGV);

die "Can't find directory `$startdir'! $!\n" unless (-d $startdir);

my %operations = (
		  'block_device' => {
				     'open' => 1,
				     'release' => 1,
				     'ioctl' => 1,
				     'check_media_change' => 1,
				     'revalidate' => 1,
				     'owner' => 1
				    },

		  'file' => {
			     'owner' => 1,
			     'llseek' => 1,
			     'read' => 1,
			     'write' => 1,
			     'readdir' => 1,
			     'poll' => 1,
			     'ioctl' => 1,
			     'mmap' => 1,
			     'open' => 1,
			     'flush' => 1,
			     'release' => 1,
			     'fsync' => 1,
			     'fasync' => 1,
			     'lock' => 1,
			     'readv' => 1,
			     'writev' => 1,
			     'sendpage' => 1,
			     'get_unmapped_area' => 1
			    },
		  'inode' => {
			      'create' => 1,
			      'lookup' => 1,
			      'link' => 1,
			      'unlink' => 1,
			      'symlink' => 1,
			      'mkdir' => 1,
			      'rmdir' => 1,
			      'mknod' => 1,
			      'rename' => 1,
			      'readlink'=> 1,
			      'follow_link' => 1,
			      'truncate' => 1,
			      'permission' => 1,
			      'revalidate' => 1,
			      'setattr' => 1,
			      'getattr' => 1
			     },
		  'super' => {
			      'read_inode' => 1,
			      'read_inode2' => 1,
			      'dirty_inode' => 1,
			      'write_inode' => 1,
			      'put_inode' => 1,
			      'delete_inode' => 1,
			      'put_super' => 1,
			      'write_super' => 1,
			      'write_super_lockfs' => 1,
			      'unlockfs' => 1,
			      'statfs' => 1,
			      'remount_fs' => 1,
			      'clear_inode' => 1,
			      'umount_begin' => 1,
			      'fh_to_dentry' => 1,
			      'dentry_to_fh' => 1,
			      'show_options' => 1
			     },
		  'dquot' => {
			      'initialize' => 1,
			      'drop' => 1,
			      'alloc_space' => 1,
			      'alloc_inode' => 1,
			      'free_space' => 1,
			      'free_inode' => 1,
			      'transfer' => 1
			     },
		  'vm' => {
			   'open' => 1,
			   'close' => 1,
			   'nopage' => 1
			   },
		  'dentry' => {
			       'd_revalidate' => 1,
			       'd_hash' => 1,
			       'd_compare' => 1,
			       'd_delete' => 1,
			       'd_release' => 1,
			       'd_iput' => 1
			       },
		  'parport' => {
				'write_data' => 1,
				'read_data' => 1,
				'write_control' => 1,
				'read_control' => 1,
				'frob_control' => 1,
				'read_status' => 1,
				'enable_irq' => 1,
				'disable_irq' => 1,
				'data_forward' => 1,
				'data_reverse' => 1,
				'init_state' => 1,
				'save_state' => 1,
				'restore_state' => 1,
				'inc_use_count' => 1,
				'dec_use_count' => 1,
				'epp_write_data' => 1,
				'epp_read_data' => 1,
				'epp_write_addr' => 1,
				'epp_read_addr' => 1,
				'ecp_write_data' => 1,
				'ecp_read_data' => 1,
				'ecp_write_addr' => 1,
				'compat_write_data' => 1,
				'nibble_read_data' => 1,
				'byte_read_data' => 1
			       },
		  'address_space' => {
				      'writepage' => 1,
				      'readpage' => 1,
				      'sync_page' => 1,
				      'prepare_write' => 1,
				      'commit_write' => 1,
				      'bmap' => 1,
				      'flushpage' => 1,
				      'releasepage' => 1,
				      'direct_IO' => 1,
				      'removepage' => 1
				      },
		  'seq' => {
			    'start' => 1,
			    'stop' => 1,
			    'next' => 1,
			    'show' => 1
			   },
		  'usb' => {
			    'allocate' => 1,
			    'deallocate' => 1,
			    'get_frame_number' => 1,
			    'submit_urb' => 1,
			    'unlink_urb' => 1
			   },
		  'fb_ops' => {
			       'owner' => 1,
			       'fb_open' => 1,
			       'fb_release' => 1,
			       'fb_get_fix' => 1,
			       'fb_get_var' => 1,
			       'fb_set_var' => 1,
			       'fb_get_cmap' => 1,
			       'fb_set_cmap' => 1,
			       'fb_pan_display' => 1,
			       'fb_ioctl' => 1,
			       'fb_mmap' => 1,
			       'fb_rastering' => 1
			       },
		  'fbgen_hwswitch' => {
				       'detect' => 1,
				       'encode_fix' => 1,
				       'decode_var' => 1,
				       'encode_var' => 1,
				       'get_par' => 1,
				       'set_par' => 1,
				       'getcolreg' => 1,
				       'setcolreg' => 1,
				       'pan_display' => 1,
				       'blank' => 1,
				       'set_disp' => 1
				       },
		  'consw' => {
			      'con_startup' => 1,
			      'con_init' => 1,
			      'con_deinit' => 1,
			      'con_clear' => 1,
			      'con_putc' => 1,
			      'con_putcs' => 1,
			      'con_cursor' => 1,
			      'con_scroll' => 1,
			      'con_bmove' => 1,
			      'con_switch' => 1,
			      'con_blank' => 1,
			      'con_fontop' => 1,
			      'con_set_palette' => 1,
			      'con_scrolldelta' => 1,
			      'con_set_origin' => 1,
			      'con_save_screen' => 1,
			      'con_build_attr' => 1,
			      'con_invert_region' => 1,
			      'con_screen_pos' => 1,
			      'con_getxy' => 1
			     },
		  'gameport_dev' => {
				 'connect' => 1,
				 'disconnect' => 1
				},
		  'ide_driver_t' => {
				     'name' => 1,
				     'version' => 1,
				     'media' => 1,
				     'busy' => 1,
				     'supports_dma' => 1,
				     'supports_dsc_overlap' => 1,
				     'cleanup' => 1,
				     'standby' => 1,
				     'suspend' => 1,
				     'resume' => 1,
				     'flushcache' => 1,
				     'do_request' => 1,
				     'end_request' => 1,
				     'sense' => 1,
				     'error' => 1,
				     'open' => 1,
				     'ioctl' => 1,
				     'release' => 1,
				     'media_change' => 1,
				     'revalidate' => 1,
				     'pre_reset' => 1,
				     'capacity' => 1,
				     'special' => 1,
				     'proc' => 1,
				     'init' => 1,
				     'reinit' => 1,
				     'ata_prebuilder' => 1,
				     'atapi_prebuilder' => 1
				    },
		  'cdrom_device_ops' => {
					 'open' => 1,
					 'release' => 1,
					 'drive_status' => 1,
					 'media_changed' => 1,
					 'tray_move' => 1,
					 'lock_door' => 1,
					 'select_speed' => 1,
					 'select_disc' => 1,
					 'get_last_session' => 1,
					 'get_mcn' => 1,
					 'reset' => 1,
					 'audio_ioctl' => 1,
					 'dev_ioctl' => 1,
					 'capability' => 1,
					 'n_minors' => 1,
					 'generate_packet' => 1,
					},
		  'cdrom_device_info' => {
					  'opts' => 1,
					  'next' => 1,
					  'handle' => 1,
					  'de' => 1,
					  'number' => 1,
					  'dev' => 1,
					  'mask' => 1,
					  'speed' => 1,
					  'capacity' => 1,
					  'options' => 1,
					  'mc_flags' => 1,
					  'use_count' => 1,
					  'name' => 1,
					  'sanyo_slot' => 1,
					  'reserved' => 1,
					  'write' => 1
					 },
		  'hw_interrupt_type' => {
					  'typename' => 1,
					  'startup' => 1,
					  'shutdown' => 1,
					  'enable' => 1,
					  'disable' => 1,
					  'ack' => 1,
					  'send' => 1,
					  'set_affinity' => 1
					 },
		  'miscdevice' => {
				   'minor' => 1,
				   'name' => 1,
				   'fops' => 1,
				   'prev' => 1,
				   'devfs_handle' => 1,
				  },
		  'usb_driver' => {
				   'name' => 1,
				   'probe' => 1,
				   'disconnect' => 1,
				   'driver_list' => 1,
				   'fops' => 1,
				   'minor' => 1,
				   'serialize' => 1,
				   'ioctl' => 1,
				   'id_table' => 1,
				   'suspend' => 1,
				   'resume' => 1,
				  },
		  'usb_serial_device_type' => {
					       'name' => 1,
					       'id_table' => 1,
					       'needs_interrupt_in' => 1,
					       'needs_bulk_in' => 1,
					       'needs_bulk_out' => 1,
					       'num_interrupt_in' => 1,
					       'num_bulk_in' => 1,
					       'num_bulk_out' => 1,
					       'num_ports' => 1,
					       'driver_list' => 1,
					       'startup' => 1,
					       'shutdown' => 1,
					       'open' => 1,
					       'close' => 1,
					       'write' => 1,
					       'write_room' => 1,
					       'ioctl' => 1,
					       'set_termios' => 1,
					       'break_ctl' => 1,
					       'chars_in_buffer' => 1,
					       'throttle' => 1,
					       'unthrottle' => 1,
					       'read_int_callback' => 1,
					       'read_bulk_callback' => 1,
					       'write_bulk_callback' => 1,
					      },
		  'pci_driver' => {
				   'node' => 1,
				   'name' => 1,
				   'id_table' => 1,
				   'probe' => 1,
				   'remove' => 1,
				   'save_state' => 1,
				   'suspend' => 1,
				   'resume' => 1,
				   'enable_wake' => 1,
				  },
		  'proto' => {
			      'close' => 1,
			      'connect' => 1,
			      'disconnect' => 1,
			      'accept' => 1,
			      'ioctl' => 1,
			      'init' => 1,
			      'destroy' => 1,
			      'shutdown' => 1,
			      'setsockopt' => 1,
			      'getsockopt' => 1,
			      'sendmsg' => 1,
			      'recvmsg' => 1,
			      'bind' => 1,
			      'backlog_rcv' => 1,
			      'hash' => 1,
			      'unhash' => 1,
			      'get_port' => 1,
			      'name' => 1,
			     },
		  'proto_ops' => {
				  'family' => 1,
				  'release' => 1,
				  'bind' => 1,
				  'connect' => 1,
				  'socketpair' => 1,
				  'accept' => 1,
				  'getname' => 1,
				  'poll' => 1,
				  'ioctl' => 1,
				  'listen' => 1,
				  'shutdown' => 1,
				  'setsockopt' => 1,
				  'getsockopt' => 1,
				  'sendmsg' => 1,
				  'recvmsg' => 1,
				  'mmap' => 1,
				  'sendpage' => 1,
				 },
		  'net_proto_family' => {
					 'family' => 1,
					 'create' => 1,
					 'autentication' => 1,
					 'encryption' => 1,
					 'encrypt_net' => 1,
					},

		  'inet_protosw' => {
				     'list' => 1,
				     'type' => 1,
				     'protocol' => 1,
				     'prot' => 1,
				     'ops' => 1,
				     'capability' => 1,
				     'no_check' => 1,
				     'flags' => 1,
				    },
		  'hci_proto' => {
				  'name' => 1,
				  'id' => 1,
				  'flags' => 1,
				  'priv' => 1,
				  'connect_ind' => 1,
				  'connect_cfm' => 1,
				  'disconn_ind' => 1,
				  'recv_acldata' => 1,
				  'recv_scodata' => 1,
				  'auth_cfm' => 1,
				  'encrypt_cfm' => 1,
				 },
		  'hci_uart_proto' => {
				       'id' => 1,
				       'open' => 1,
				       'recv' => 1,
				       'send' => 1,
				       'close' => 1,
				       'flush' => 1,
				       'preq' => 1,
				      },
		 );
		
my @dirs = ();
push(@dirs,$startdir);

while(defined(my $dir = pop(@dirs))) {
  opendir(DIR,$dir) || die "Can't open directory `$dir'! $!\n";
  my @files = grep(!/^\.\.?$/, readdir(DIR));
  closedir(DIR);
  foreach (@files) {
    my $fname = join("/", $dir, $_);
    if (-d $fname) {
      push(@dirs, $fname);
      next;
    }
    next unless ($fname =~ /\.c$/);
    open(CFILE,"<$fname") || die "Can't open `$fname'! $!\n";
    my @newlines = ();
    my $opflag = 0;
    my $writeflag = 0;
    my $key = '';
    while(<CFILE>) {
      if (/(block_device|file|inode|super|dquot|vm|dentry|parport|address_space|seq|usb)_operations\s+\S+\s+\=/) {
	$key = $1;
	$opflag = 1;
      } elsif (/\s(miscdevice|cdrom_device_ops|ide_driver_t|usb_driver|usb_serial_device_type|pci_driver|proto|proto_ops|inet_protosw)\s+\S+\s+\=/) {
	$key = $1;
	$opflag = 1;
      } else {
	if (/\s(consw|fb_ops|fbgen_hwswitch|gameport_dev|net_proto_family|hci_proto|hci_uart_proto)\s+\S+\s+\=/) {
	  $key = $1;
	  $opflag = 1;
	}
      }
      unless ($opflag) {
	push(@newlines,$_);
	next;
      }
      if (m!([^\w\s]+)\s*([\w_]+):\s*(.+)$!) {
	if (exists($operations{$key}->{$2})) {
	  $writeflag++;
	  push(@newlines,"\t$1 .$2 = $3\n");
	} else {
	  push(@newlines,$_);
	}
      } elsif (m!([\w_]+):\s*(.+)$!) {
	if (exists($operations{$key}->{$1})) {
	  $writeflag++;
	  push(@newlines,"\t.$1 = $2\n");
	} else {
	  push(@newlines,$_);
	}
      } else{
	push(@newlines,$_);
      }
      if (m!\};!) {
	$opflag = 0;
      }
    }
    close(CFILE);
    if ($writeflag) {
      my $newname = join(".", $fname, 'new');
      open(NEWFILE,">$newname") || die "Can't create `$newname'! $!\n";
      print NEWFILE @newlines;
      close(NEWFILE) || die "Error writing `$newname'! $!\n";
      my $oldname = join(".", $fname, 'old');
      rename($fname, $oldname) || die "Can't rename '$fname'! $!\n";
      rename($newname, $fname) || die "Can't rename '$newname'! $!\n";
    }
  }
}

