Home | History | Annotate | Line # | Download | only in auto
      1  1.1  christos # ==========================================
      2  1.1  christos #   Unity Project - A Test Framework for C
      3  1.1  christos #   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
      4  1.1  christos #   [Released under MIT License. Please refer to license.txt for details]
      5  1.1  christos # ========================================== 
      6  1.1  christos 
      7  1.1  christos # This script creates all the files with start code necessary for a new module.
      8  1.1  christos # A simple module only requires a source file, header file, and test file.
      9  1.1  christos # Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
     10  1.1  christos 
     11  1.1  christos require 'rubygems'
     12  1.1  christos require 'fileutils'
     13  1.1  christos 
     14  1.1  christos HERE = File.expand_path(File.dirname(__FILE__)) + '/'
     15  1.1  christos 
     16  1.1  christos #help text when requested
     17  1.1  christos HELP_TEXT = [ "\nGENERATE MODULE\n-------- ------",
     18  1.1  christos               "\nUsage: ruby generate_module [options] module_name",
     19  1.1  christos               "  -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
     20  1.1  christos               "  -s\"../src\"  sets the path to output source to '../src'   (DEFAULT ../src)",
     21  1.1  christos               "  -t\"C:/test\" sets the path to output source to 'C:/test'  (DEFAULT ../test)",
     22  1.1  christos               "  -p\"MCH\"     sets the output pattern to MCH.",
     23  1.1  christos               "              dh  - driver hardware.",
     24  1.1  christos               "              dih - driver interrupt hardware.",
     25  1.1  christos               "              mch - model conductor hardware.",
     26  1.1  christos               "              mvp - model view presenter.",
     27  1.1  christos               "              src - just a single source module. (DEFAULT)",
     28  1.1  christos               "  -d          destroy module instead of creating it.",
     29  1.1  christos               "  -u          update subversion too (requires subversion command line)",
     30  1.1  christos               "  -y\"my.yml\"  selects a different yaml config file for module generation",
     31  1.1  christos               "" ].join("\n")
     32  1.1  christos 
     33  1.1  christos #Built in patterns
     34  1.1  christos PATTERNS = { 'src' => {''         => { :inc => [] } },
     35  1.1  christos              'dh'  => {'Driver'   => { :inc => ['%1$sHardware.h'] }, 
     36  1.1  christos                        'Hardware' => { :inc => [] } 
     37  1.1  christos                       },
     38  1.1  christos              'dih' => {'Driver'   => { :inc => ['%1$sHardware.h', '%1$sInterrupt.h'] }, 
     39  1.1  christos                        'Interrupt'=> { :inc => ['%1$sHardware.h'] },
     40  1.1  christos                        'Hardware' => { :inc => [] } 
     41  1.1  christos                       },
     42  1.1  christos              'mch' => {'Model'    => { :inc => [] }, 
     43  1.1  christos                        'Conductor'=> { :inc => ['%1$sModel.h', '%1$sHardware.h'] },
     44  1.1  christos                        'Hardware' => { :inc => [] } 
     45  1.1  christos                       },
     46  1.1  christos              'mvp' => {'Model'    => { :inc => [] }, 
     47  1.1  christos                        'Presenter'=> { :inc => ['%1$sModel.h', '%1$sView.h'] },
     48  1.1  christos                        'View'     => { :inc => [] } 
     49  1.1  christos                       }
     50  1.1  christos            }
     51  1.1  christos 
     52  1.1  christos #TEMPLATE_TST
     53  1.1  christos TEMPLATE_TST = %q[#include "unity.h"
     54  1.1  christos %2$s#include "%1$s.h"
     55  1.1  christos 
     56  1.1  christos void setUp(void)
     57  1.1  christos {
     58  1.1  christos }
     59  1.1  christos 
     60  1.1  christos void tearDown(void)
     61  1.1  christos {
     62  1.1  christos }
     63  1.1  christos 
     64  1.1  christos void test_%1$s_NeedToImplement(void)
     65  1.1  christos {
     66  1.1  christos     TEST_IGNORE();
     67  1.1  christos }
     68  1.1  christos ]
     69  1.1  christos 
     70  1.1  christos #TEMPLATE_SRC
     71  1.1  christos TEMPLATE_SRC = %q[%2$s#include "%1$s.h"
     72  1.1  christos ]
     73  1.1  christos 
     74  1.1  christos #TEMPLATE_INC
     75  1.1  christos TEMPLATE_INC = %q[#ifndef _%3$s_H
     76  1.1  christos #define _%3$s_H%2$s
     77  1.1  christos 
     78  1.1  christos #endif // _%3$s_H
     79  1.1  christos ]
     80  1.1  christos 
     81  1.1  christos # Parse the command line parameters.
     82  1.1  christos ARGV.each do |arg|
     83  1.1  christos   case(arg)
     84  1.1  christos     when /^-d/      then @destroy = true
     85  1.1  christos     when /^-u/      then @update_svn = true
     86  1.1  christos     when /^-p(\w+)/ then @pattern = $1
     87  1.1  christos     when /^-s(.+)/  then @path_src = $1
     88  1.1  christos     when /^-i(.+)/  then @path_inc = $1
     89  1.1  christos     when /^-t(.+)/  then @path_tst = $1
     90  1.1  christos     when /^-y(.+)/  then @yaml_config = $1
     91  1.1  christos     when /^(\w+)/
     92  1.1  christos       raise "ERROR: You can't have more than one Module name specified!" unless @module_name.nil?
     93  1.1  christos       @module_name = arg
     94  1.1  christos     when /^-(h|-help)/ 
     95  1.1  christos       puts HELP_TEXT
     96  1.1  christos       exit
     97  1.1  christos     else
     98  1.1  christos       raise "ERROR: Unknown option specified '#{arg}'"
     99  1.1  christos   end
    100  1.1  christos end
    101  1.1  christos raise "ERROR: You must have a Module name specified! (use option -h for help)" if @module_name.nil?
    102  1.1  christos 
    103  1.1  christos #load yaml file if one was requested
    104  1.1  christos if @yaml_config
    105  1.1  christos   require 'yaml'
    106  1.1  christos   cfg = YAML.load_file(HERE + @yaml_config)[:generate_module]
    107  1.1  christos   @path_src     = cfg[:defaults][:path_src]   if @path_src.nil?
    108  1.1  christos   @path_inc     = cfg[:defaults][:path_inc]   if @path_inc.nil?
    109  1.1  christos   @path_tst     = cfg[:defaults][:path_tst]   if @path_tst.nil?
    110  1.1  christos   @update_svn   = cfg[:defaults][:update_svn] if @update_svn.nil?
    111  1.1  christos   @extra_inc    = cfg[:includes]
    112  1.1  christos   @boilerplates = cfg[:boilerplates]
    113  1.1  christos else
    114  1.1  christos   @boilerplates = {}
    115  1.1  christos end
    116  1.1  christos 
    117  1.1  christos # Create default file paths if none were provided
    118  1.1  christos @path_src = HERE + "../src/"  if @path_src.nil?
    119  1.1  christos @path_inc = @path_src         if @path_inc.nil?
    120  1.1  christos @path_tst = HERE + "../test/" if @path_tst.nil?
    121  1.1  christos @path_src += '/'              unless (@path_src[-1] == 47)
    122  1.1  christos @path_inc += '/'              unless (@path_inc[-1] == 47)
    123  1.1  christos @path_tst += '/'              unless (@path_tst[-1] == 47)
    124  1.1  christos @pattern  = 'src'             if @pattern.nil?
    125  1.1  christos @includes = { :src => [], :inc => [], :tst => [] }
    126  1.1  christos @includes.merge!(@extra_inc) unless @extra_inc.nil?
    127  1.1  christos 
    128  1.1  christos #create triad definition
    129  1.1  christos TRIAD = [ { :ext => '.c', :path => @path_src,        :template => TEMPLATE_SRC, :inc => :src, :boilerplate => @boilerplates[:src] }, 
    130  1.1  christos           { :ext => '.h', :path => @path_inc,        :template => TEMPLATE_INC, :inc => :inc, :boilerplate => @boilerplates[:inc] },
    131  1.1  christos           { :ext => '.c', :path => @path_tst+'Test', :template => TEMPLATE_TST, :inc => :tst, :boilerplate => @boilerplates[:tst] },
    132  1.1  christos         ]
    133  1.1  christos 
    134  1.1  christos #prepare the pattern for use
    135  1.1  christos @patterns = PATTERNS[@pattern.downcase]
    136  1.1  christos raise "ERROR: The design pattern specified isn't one that I recognize!" if @patterns.nil?
    137  1.1  christos 
    138  1.1  christos # Assemble the path/names of the files we need to work with.
    139  1.1  christos files = []
    140  1.1  christos TRIAD.each do |triad|
    141  1.1  christos   @patterns.each_pair do |pattern_file, pattern_traits|
    142  1.1  christos     files << {
    143  1.1  christos       :path => "#{triad[:path]}#{@module_name}#{pattern_file}#{triad[:ext]}",
    144  1.1  christos       :name => "#{@module_name}#{pattern_file}",
    145  1.1  christos       :template => triad[:template],
    146  1.1  christos       :boilerplate => triad[:boilerplate],
    147  1.1  christos       :includes => case(triad[:inc])
    148  1.1  christos                      when :src then @includes[:src] | pattern_traits[:inc].map{|f| f % [@module_name]}
    149  1.1  christos                      when :inc then @includes[:inc]
    150  1.1  christos                      when :tst then @includes[:tst] | pattern_traits[:inc].map{|f| "Mock#{f}"% [@module_name]}
    151  1.1  christos                    end
    152  1.1  christos     }
    153  1.1  christos   end
    154  1.1  christos end
    155  1.1  christos 
    156  1.1  christos # destroy files if that was what was requested
    157  1.1  christos if @destroy
    158  1.1  christos   files.each do |filespec|
    159  1.1  christos     file = filespec[:path]
    160  1.1  christos     if File.exist?(file)
    161  1.1  christos       if @update_svn
    162  1.1  christos         `svn delete \"#{file}\" --force` 
    163  1.1  christos         puts "File #{file} deleted and removed from source control"
    164  1.1  christos       else
    165  1.1  christos         FileUtils.remove(file)
    166  1.1  christos         puts "File #{file} deleted"
    167  1.1  christos       end
    168  1.1  christos     else
    169  1.1  christos       puts "File #{file} does not exist so cannot be removed."
    170  1.1  christos     end
    171  1.1  christos   end
    172  1.1  christos   puts "Destroy Complete"
    173  1.1  christos   exit
    174  1.1  christos end
    175  1.1  christos 
    176  1.1  christos #Abort if any module already exists
    177  1.1  christos files.each do |file|
    178  1.1  christos   raise "ERROR: File #{file[:name]} already exists. Exiting." if File.exist?(file[:path])
    179  1.1  christos end
    180  1.1  christos 
    181  1.1  christos # Create Source Modules
    182  1.1  christos files.each_with_index do |file, i|
    183  1.1  christos   File.open(file[:path], 'w') do |f|
    184  1.1  christos     f.write(file[:boilerplate] % [file[:name]]) unless file[:boilerplate].nil?
    185  1.1  christos     f.write(file[:template] % [ file[:name], 
    186  1.1  christos                                 file[:includes].map{|f| "#include \"#{f}\"\n"}.join, 
    187  1.1  christos                                 file[:name].upcase ]
    188  1.1  christos            )
    189  1.1  christos   end
    190  1.1  christos   if (@update_svn)
    191  1.1  christos     `svn add \"#{file[:path]}\"` 
    192  1.1  christos     if $?.exitstatus == 0
    193  1.1  christos       puts "File #{file[:path]} created and added to source control"
    194  1.1  christos     else
    195  1.1  christos       puts "File #{file[:path]} created but FAILED adding to source control!"
    196  1.1  christos     end
    197  1.1  christos   else
    198  1.1  christos     puts "File #{file[:path]} created"
    199  1.1  christos   end
    200  1.1  christos end
    201  1.1  christos 
    202  1.1  christos puts 'Generate Complete'
    203