File: ragel_extension_task.rb

package info (click to toggle)
ruby-redcloth 4.3.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 708 kB
  • sloc: ruby: 1,233; ansic: 201; makefile: 25
file content (116 lines) | stat: -rw-r--r-- 2,933 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
module Rake
  module RagelGenerationTasks
    RAGEL_INCLUDE_PATTERN = /include \w+ "([^"]+)";/
    RAGEL_VERSION_COMMAND = "ragel -v"
    
    attr_accessor :rl_dir
    attr_accessor :machines
    
    def init(name = nil, gem_spec = nil)
      super
      
      @rl_dir = "ragel"
      @machines = %w(scan inline attributes)
    end
    
    def lang
      raise NotImplementedError
    end
    
    def source_files
      @source_files ||= machines.map {|m| target(m) }
    end
    
    def define
      super
      define_ragel_tasks
    end
    
    def define_ragel_tasks
      machines.each do |machine|
        file target(machine) => [*ragel_sources(machine)] do
          mkdir_p(File.dirname(target(machine))) unless File.directory?(File.dirname(target(machine)))
          ensure_ragel_version
          sh "ragel #{flags} #{lang_ragel(machine)} -o #{target(machine)}"
        end
        
        file extconf => [target(machine)] if lang == 'c'
      end
    end

    def target(machine)
      {
        'scan' => {
          'c'    => "#{@ext_dir}/redcloth_scan.c",
          'rb'   => "#{@ext_dir}/redcloth_scan.rb"
        },
        'inline' => {
          'c'    => "#{@ext_dir}/redcloth_inline.c",
          'rb'   => "#{@ext_dir}/redcloth_inline.rb"
        },
        'attributes' => {
          'c'    => "#{@ext_dir}/redcloth_attributes.c",
          'rb'   => "#{@ext_dir}/redcloth_attributes.rb"
        }
      }[machine][lang]
    end

    def lang_ragel(machine)
      "#{@rl_dir}/redcloth_#{machine}.#{lang}.rl"
    end

    def ragel_sources(machine)
      deps = [lang_ragel(machine), ragel_file_dependencies(lang_ragel(machine))].flatten.dup
      deps += ["#{@ext_dir}/redcloth.h"] if lang == 'c'
      deps
      # FIXME: merge that header file into other places so it can be eliminated?
    end
    
    def ragel_file_dependencies(ragel_file)
      found = find_ragel_includes(ragel_file)
      found + found.collect {|file| ragel_file_dependencies(file)}
    end
    
    def find_ragel_includes(file)
      File.open(file).grep(RAGEL_INCLUDE_PATTERN) { $1 }.map do |file|
        "#{@rl_dir}/#{file}"
      end
    end

    def flags
      code_style_flag = preferred_code_style ? " -" + preferred_code_style : ""
      "-#{host_language_flag}#{code_style_flag}"
    end

    def host_language_flag
      {
        'c'      => 'C',
        'rb'     => 'R'
      }[lang]
    end

    def preferred_code_style
      {
        'c'      => 'T0',
        'rb'     => 'F1'
      }[lang]
    end

    def ensure_ragel_version
      @ragel_v ||= `ragel -v`[/(version )(\S*)/,2].split('.').map{|s| s.to_i}
      raise unless @ragel_v[0] > 6 || (@ragel_v[0] == 6 && @ragel_v[1] >= 3)
    rescue
      STDERR.puts "Ragel 6.3 or greater is required."
      exit(1)
    end
    
  end
  class RagelExtensionTask < ExtensionTask
    include RagelGenerationTasks

    def lang
      "c"
    end
  end  
  
end