crun 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 673e146fb17b31e94d8c3eb0b07211588037ccac
4
- data.tar.gz: 37512566a420652eaf9eb98dd7a18e2b493e05b7
3
+ metadata.gz: fdbb73ff120ce8d6c877f040acd9dae16b2ad0d3
4
+ data.tar.gz: 9b9273e32f0366ba3639c709741416e2d840e384
5
5
  SHA512:
6
- metadata.gz: 7b9040aaed86d5d3c831c7b57d8a86d7ac839661ee025c974975debf6be6a9f828386489b8a583d1973b18acffdecc8ab5847d3c8ad01f3da53af801c5db9cc3
7
- data.tar.gz: 0b2a5e8cc7c95c871a8b6d2fd8f0d0cab547dd4c4b09d4ea5c5d784dabe6a267fa22101d1af6ebe52dc0ddccfbb5f872d432efcfdded29728049c692beb5c8b8
6
+ metadata.gz: 6b985a96db0b25032904b6c0089d0a915477f278d38e665f785d60c40018a7d34ad649604ece9222bd5052351a71e398dfd42862b63f78f0b691ac9fcaba4814
7
+ data.tar.gz: 22ebcd85b9ebdfeb88eabd3101093781183753d294634f057241f9cb2992c5ff66d4295bd588210022087236f911a95b89189a28ef5df7a001ef2c9e75a28edd
@@ -1,5 +1,8 @@
1
1
  = Version history
2
2
 
3
+ [0.0.4] Autoheader mode.
4
+ Documentation improvements.
5
+
3
6
  [0.0.3] Option to save the binary.
4
7
 
5
8
  [0.0.2] Option prepend feature.
@@ -11,8 +11,8 @@
11
11
  Crun is an utility for compiling and running C-programs straight from
12
12
  C source files. Crun supports compile-run and compile-debug flows.
13
13
 
14
- You can embed custom compile options into the main c-file, if you
15
- need, for example, an external library for the program. You can also
14
+ User can embed custom compile options into the main c-file, if user
15
+ need, for example, an external library for the program. User can also
16
16
  control the command line parameters passed to the program through
17
17
  Crun.
18
18
 
@@ -22,14 +22,29 @@ the list of files. Crun is targeted for small C-programs, so it is not
22
22
  typical to have multiple files.
23
23
 
24
24
  User of Crun is most probably trying out some basic C-features or maybe
25
- prototyping with some algorithm.
25
+ prototyping with some algorithm.
26
+
27
+ User can avoid listing stardard POSIX headers, if the Autoheader mode
28
+ is used. Autoheader mode will silently add "#include" directives to
29
+ the start of source files for user.
30
+
31
+ In Autoheader mode, the source files are examined for function
32
+ calls. The function calls that are part of POSIX, will get the
33
+ corresponding header files automatically included. Other libraries
34
+ (and includes) are not handled, since the possibility for ambiguous
35
+ function names are too high. Autoheader mode is activated with "-a"
36
+ option. Before Autoheader mode is used, user should update the
37
+ Autoheader DB:
38
+
39
+ shell> auto -u
40
+
26
41
 
27
42
 
28
43
  = Example runs
29
44
 
30
- In order to run "Hello World" example with Crun, you need to have the
45
+ In order to run "Hello World" example with Crun, user need to have the
31
46
  C source file with "Hello World" program in it. This is available in
32
- the "examples" directory for you.
47
+ the "examples" directory for user.
33
48
 
34
49
  "hello.c" content:
35
50
 
@@ -40,7 +55,7 @@ the "examples" directory for you.
40
55
  return 0;
41
56
  }
42
57
 
43
- You can execute compile-run flow by:
58
+ User can execute compile-run flow by:
44
59
 
45
60
  shell> crun -f examples/hello.c
46
61
 
@@ -48,7 +63,7 @@ The output from program is:
48
63
 
49
64
  Hello World!
50
65
 
51
- You can execute compile-debug flow by:
66
+ User can execute compile-debug flow by:
52
67
 
53
68
  shell> crun -f examples/hello.c -d
54
69
 
@@ -62,7 +77,7 @@ Check available command line interface, CLI, options for Crun:
62
77
 
63
78
  = Options
64
79
 
65
- You can specify options for Crun in multiple ways. Typically CLI is
80
+ User can specify options for Crun in multiple ways. Typically CLI is
66
81
  used to control Crun, but if the program uses static compilation
67
82
  options, those live most naturally in the source file itself.
68
83
 
@@ -96,7 +111,7 @@ Here is the complete list of options that control Crun:
96
111
  [ compprog ]
97
112
 
98
113
  Array including the compiler name and base options. This options
99
- array should only have one entry, but in theory you could have
114
+ array should only have one entry, but in theory user could have
100
115
  multiple entries. The entries are concatenated with SPACE. The
101
116
  compiler command has to have same command line parameters as
102
117
  "gcc". Default is: ["gcc", "-Wall", "-std=c11"].
@@ -104,7 +119,7 @@ Here is the complete list of options that control Crun:
104
119
  [ dbugprog ]
105
120
 
106
121
  Array including the debugger name and base options. This options
107
- array should only have one entry, but in theory you could have
122
+ array should only have one entry, but in theory user could have
108
123
  multiple entries. The entries are concatenated with SPACE. The
109
124
  debugger command has to have same command line parameters as
110
125
  "gdb". Default is: ["gdb", "--nx"].
@@ -138,7 +153,7 @@ User can specify static overrides in "$HOME/.crun" file and/or in
138
153
  "-c" Crun CLI option to read in option overrides.
139
154
 
140
155
  For example if the program is always run with "-c 10" command line
141
- options, you use this in ".crun":
156
+ options, user can set in ".crun":
142
157
 
143
158
  @crun['progopts'] = [ "-c 10" ]
144
159
 
@@ -148,19 +163,22 @@ use the -o option:
148
163
  shell> crun -o "progopts:=-c 10" ...
149
164
 
150
165
  This sets the list of program options to "-c 10". ":=" syntax means
151
- setting the Array of options. If you need to add to existing list of
152
- options, you should do:
166
+ setting the Array of options. If user needs to add to existing list of
167
+ options, perform:
153
168
 
154
169
  shell> crun -o "progopts:+-c 10" ...
155
170
 
156
171
  Thus ":+" is the syntax for appending more options to existing list.
157
172
 
173
+ If user wants to put an option to start of list, the ":." syntax is
174
+ used.
175
+
158
176
  The simplest way to pass 'progopts' to target program is using the
159
177
  "-p" CLI option. However user must be aware of the shell option
160
178
  parsing, since it is very easy to miss the target program and actually
161
179
  pass the option to Crun.
162
180
 
163
- If you want to pass '-' based option to target program:
181
+ If user wants to pass '-' based option to target program:
164
182
 
165
183
  shell> crun -p "\-c 10" ...
166
184
 
@@ -177,8 +195,10 @@ Summary of option setting from first to last:
177
195
  * "-o" options from Crun CLI.
178
196
  * "-p" options for program (only).
179
197
 
198
+ The options are applied in this order, and later options may override
199
+ the earlier settings, i.e. CLI options have the highest priority.
180
200
 
181
201
  = Issues
182
202
 
183
- If you take C source input from STDIN, you can't use the debug
184
- option. Only compile-run flow is possible.
203
+ If user takes C source input from STDIN, debug option can't be
204
+ used. Only compile-run flow is possible.
data/bin/crun CHANGED
@@ -11,6 +11,10 @@ require 'como'
11
11
  include Como
12
12
  require 'tempfile'
13
13
  require_relative '../lib/version'
14
+ require 'yaml'
15
+
16
+ # require 'byebug'
17
+
14
18
 
15
19
  Spec.command( 'crun', 'Tero Isannainen', '2016',
16
20
  [
@@ -18,14 +22,18 @@ Spec.command( 'crun', 'Tero Isannainen', '2016',
18
22
  [ :opt_single, 'prog', '-p', "Add program options (i.e. progopts)." ],
19
23
  [ :switch, 'debug', '-d', "Debug program." ],
20
24
  [ :opt_multi, 'opts', '-o', "Set/add crun option." ],
25
+ [ :switch, 'auto', '-a', "Use Autoheader mode." ],
21
26
  [ :opt_multi, 'conf', '-c', "Crun option file(s)." ],
22
27
  [ :switch, 'input', '-i', "Read stdin for C-code." ],
23
28
  [ :opt_single, 'save', '-s', "Save compiled file." ],
24
- [ :exclusive, 'template','-t', "Output a template file for program." ],
25
29
  [ :switch, 'verbose', '-v', "Verbose (to stderr)." ],
30
+ [ :switch, 'template','-t', "Output a template file for program." ],
31
+ [ :switch, 'database','-u', "Update DB for Autoheader mode." ],
26
32
  ] )
27
33
 
28
34
 
35
+ CRUN_HEADERS = "#{ENV['HOME']}/.crun_headers"
36
+
29
37
  # Execute shell command with optional verbosity.
30
38
  def crun_exe( cmd )
31
39
  if Opt['verbose'].given
@@ -34,17 +42,28 @@ def crun_exe( cmd )
34
42
  system( cmd )
35
43
  end
36
44
 
45
+
37
46
  # Parse and apply option setting.
38
47
  def apply_opt( opt )
48
+
39
49
  if opt.split(':=').length == 2
50
+
51
+ # Create option array.
40
52
  parts = opt.split(':=')
41
53
  @crun[parts[0]] = [ parts[1] ]
54
+
42
55
  elsif opt.split(':+').length == 2
56
+
57
+ # Add to existing option array.
43
58
  parts = opt.split(':+')
44
59
  @crun[parts[0]].push parts[1]
60
+
45
61
  elsif opt.split(':.').length == 2
62
+
63
+ # Put option to start of list.
46
64
  parts = opt.split(':.')
47
65
  @crun[parts[0]].unshift parts[1]
66
+
48
67
  end
49
68
  end
50
69
 
@@ -67,19 +86,135 @@ int main( int argc, char** argv )
67
86
  end
68
87
 
69
88
 
89
+ if Opt['database'].given
90
+ require_relative '../lib/parsec'
91
+
92
+ posix_headers = %w{
93
+ <aio.h> <libgen.h> <spawn.h> <sys/time.h>
94
+ <arpa/inet.h> <limits.h> <stdarg.h> <sys/times.h>
95
+ <assert.h> <locale.h> <stdbool.h> <sys/types.h>
96
+ <complex.h> <math.h> <stddef.h> <sys/uio.h>
97
+ <cpio.h> <monetary.h> <stdint.h> <sys/un.h>
98
+ <ctype.h> <mqueue.h> <stdio.h> <sys/utsname.h>
99
+ <dirent.h> <ndbm.h> <stdlib.h> <sys/wait.h>
100
+ <dlfcn.h> <net/if.h> <string.h> <syslog.h>
101
+ <errno.h> <netdb.h> <strings.h> <tar.h>
102
+ <fcntl.h> <netinet/in.h> <stropts.h> <termios.h>
103
+ <fenv.h> <netinet/tcp.h> <sys/ipc.h> <tgmath.h>
104
+ <float.h> <nl_types.h> <sys/mman.h> <time.h>
105
+ <fmtmsg.h> <poll.h> <sys/msg.h> <trace.h>
106
+ <fnmatch.h> <pthread.h> <sys/resource.h> <ulimit.h>
107
+ <ftw.h> <pwd.h> <sys/select.h> <unistd.h>
108
+ <glob.h> <regex.h> <sys/sem.h> <utime.h>
109
+ <grp.h> <sched.h> <sys/shm.h> <utmpx.h>
110
+ <iconv.h> <search.h> <sys/socket.h> <wchar.h>
111
+ <inttypes.h> <semaphore.h> <sys/stat.h> <wctype.h>
112
+ <iso646.h> <setjmp.h> <sys/statvfs.h> <wordexp.h>
113
+ <langinfo.h> <signal.h>
114
+ }
115
+
116
+ func_header_map = {}
117
+
118
+ posix_headers.each do |header|
119
+ base = header[1..-2]
120
+
121
+ headername = "/usr/include/" + base
122
+
123
+ if File.exist?( headername )
124
+ file = ParseC::SourceFile.new( headername, "/usr/include" )
125
+ file.conf( :defsonly, true )
126
+ # file.conf( :mainonly, true )
127
+ file.conf( :mainonly, false )
128
+ file.parse
129
+
130
+ file.funcdefs.each do |k,v|
131
+ if k[0..1] != "__"
132
+ func_header_map[ k ] = header
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ File.write( CRUN_HEADERS, YAML.dump( func_header_map ) )
139
+
140
+ exit( false )
141
+ end
142
+
143
+
144
+ # C-source file object.
145
+ class SourceFile
146
+
147
+ def initialize( name )
148
+ # Original name.
149
+ @name = name
150
+
151
+ # Current path to compile filed.
152
+ @path = name
153
+
154
+ # Temp file to remove (if any).
155
+ @remove = nil
156
+ end
157
+
158
+ def headerize
159
+ require_relative '../lib/parsec'
160
+
161
+ func_header_map = nil
162
+ if File.exist? CRUN_HEADERS
163
+ func_header_map = YAML.load( File.read( CRUN_HEADERS ) )
164
+ else
165
+ return
166
+ end
167
+
168
+ base = File.basename( @name, ".c" )
169
+ @path = "/dev/shm/auto-#{base}.c"
170
+ parse = ParseC::SourceFile.new( @name, File.dirname( @name ) )
171
+ parse.conf( :mainonly, true )
172
+ parse.parse
173
+
174
+ autoheaders = {}
175
+
176
+ parse.funcalls.each do |k,v|
177
+ if func_header_map[ k ]
178
+ autoheaders[ func_header_map[ k ] ] = true
179
+ end
180
+ end
181
+
182
+ fh = File.open( @path, "w" )
183
+ autoheaders.each do |k,v|
184
+ fh.write( "#include #{k}\n" )
185
+ end
186
+ fh.write( File.read( @name ) )
187
+ fh.close
188
+
189
+ # Set file to be removed.
190
+ @remove = @path
191
+ end
192
+
193
+ def path
194
+ @path
195
+ end
196
+
197
+ def delete
198
+ FileUtils.rm_f( @remove ) if @remove
199
+ end
200
+ end
201
+
202
+
203
+
70
204
  if Opt['file'].given
71
- cfiles = Opt['file'].value
205
+ cfiles = Opt['file'].value.map{ |i| SourceFile.new( i ) }
72
206
  elsif Opt['input'].given
73
207
  # Create a temp c-file for input.
74
208
  input = STDIN.read
75
209
  cfile = "#{Tempfile.new( "crun-source", '/dev/shm' ).path}.c"
76
210
  File.write( cfile, input )
77
- cfiles = [ cfile ]
211
+ cfiles = [ SourceFile.new( cfile ) ]
78
212
  else
79
213
  Spec.usage
80
214
  end
81
215
 
82
216
 
217
+
83
218
  # ------------------------------------------------------------
84
219
  # Configurations:
85
220
 
@@ -126,7 +261,7 @@ end
126
261
  compopts = @crun['compopts']
127
262
  crun_re = /[\s]+crun-([a-z]+)/
128
263
 
129
- File.readlines( cfiles[0] ).each do |line|
264
+ File.readlines( cfiles[0].path ).each do |line|
130
265
  m = line.match( crun_re )
131
266
  if m
132
267
  option = m[1]
@@ -163,7 +298,7 @@ end
163
298
 
164
299
  # ------------------------------------------------------------
165
300
  # Create tempfile for executable.
166
- exefile = File.basename( cfiles[0], '.c' )
301
+ exefile = File.basename( cfiles[0].path, '.c' )
167
302
  exepath = Tempfile.new( "crun-#{exefile}", '/dev/shm' ).path
168
303
 
169
304
 
@@ -178,7 +313,16 @@ class Array
178
313
  end
179
314
  end
180
315
 
181
- cmds.push "#{@crun['compprog'].crun} #{@crun['crunopts'].crun} #{@crun['compopts'].crun} #{cfiles.crun} -o #{exepath}"
316
+ # Autoheader source files if needed.
317
+ if Opt['auto'].given
318
+ cfiles.each do |cfile|
319
+ cfile.headerize
320
+ end
321
+ end
322
+
323
+ cfile_paths = cfiles.map{ |i| i.path }
324
+
325
+ cmds.push "#{@crun['compprog'].crun} #{@crun['crunopts'].crun} #{@crun['compopts'].crun} #{cfile_paths.crun} -o #{exepath}"
182
326
 
183
327
  # In order to avoid the "text file busy" issue, copy back and forth the exefile.
184
328
  cmds.push "cp #{exepath} #{exepath}-tmp"
@@ -230,7 +374,11 @@ end
230
374
  # ------------------------------------------------------------
231
375
  # Always cleanup, but not necessary if using "/dev/shm".
232
376
  if Opt['input'].given
233
- system( "rm -f #{cfiles[0]}" )
377
+ system( "rm -f #{cfiles[0].name}" )
378
+ end
379
+
380
+ cfiles.each do |cfile|
381
+ cfile.delete
234
382
  end
235
383
 
236
384
  FileUtils.rm_f exepath
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Options for crun:
3
+ * -crun-compopts:=-O2
4
+ * crun-compopts:+-lm
5
+ * crun-compopts:.-std=c99
6
+ * crun-compopts:.-std=c11
7
+ * crun-progopts:=-c 12
8
+ */
9
+
10
+ int main( int argc, char** argv )
11
+ {
12
+ char* greeting = "Greetings!\n";
13
+ char* greeting_n = "Greeting #%d!\n";
14
+
15
+ int strlenlog;
16
+ strlenlog = log2( strlen( greeting ) );
17
+
18
+ if ( strlenlog > 10 )
19
+ exit( 1 );
20
+
21
+ int times = 1;
22
+ if ( argc > 1 )
23
+ {
24
+ if ( !strcmp( argv[1], "-c" ) )
25
+ sscanf( argv[2], "%d", &times );
26
+ else
27
+ {
28
+ fprintf( stderr, "Usage: greeting [-c count]\n" );
29
+ exit( 1 );
30
+ }
31
+ }
32
+
33
+ if ( times > 1 )
34
+ {
35
+ for ( int i = 0; i < times; i++ )
36
+ printf( greeting_n, i+1 );
37
+ }
38
+ else
39
+ {
40
+ printf( greeting );
41
+ }
42
+
43
+ return 0;
44
+ }
@@ -0,0 +1,311 @@
1
+ # Detect suitable CLANG library
2
+ unless ENV['LIBCLANG']
3
+ begin
4
+ libdir = %x{llvm-config --libdir}.chomp
5
+ libs = Dir.glob( "#{libdir}/*libclang*so*" )
6
+ ENV['LIBCLANG'] = libs[0]
7
+ rescue
8
+ raise RuntimeError, "Could not find LLVM, try setting LIBCLANG to library!"
9
+ end
10
+ end
11
+
12
+
13
+
14
+ # require 'ffi/clang' display stupid messages to stdout, silence them.
15
+ begin
16
+ require "stringio"
17
+ old_stdout, $stdout = $stdout, StringIO.new
18
+ require 'ffi/clang'
19
+ $stdout = old_stdout
20
+ end
21
+
22
+ # C-parsing module based on libclang and ffi/clang, i.e. ffi bindings.
23
+ #
24
+ # @example
25
+ # require 'parsec'
26
+ # ast = ParseC::SourceFile.new( './code_out.c', '.' )
27
+ #
28
+ module ParseC
29
+
30
+ # Source file contains C-function definitions and header file
31
+ # inclusions.
32
+ class SourceFile
33
+
34
+ # File name.
35
+ attr_reader :name
36
+
37
+ def SourceFile.parseLocalDefs( name, headerPath )
38
+ file = SourceFile.new( name, headerPath )
39
+ file.conf( :defsonly, true )
40
+ file.conf( :mainonly, true )
41
+ file.parse
42
+ file
43
+ end
44
+
45
+
46
+ # Set file to parse and path for header search. Finally,
47
+ # perform parsing for the file.
48
+ def initialize( name, headerPath )
49
+ @name = name
50
+ @headerPath = headerPath
51
+
52
+ @localHeader = {}
53
+ @funcdefs = {}
54
+ @funcalls = {}
55
+
56
+ @conf = {}
57
+ @conf[ :defsonly ] = false
58
+ @conf[ :mainonly ] = false
59
+ end
60
+
61
+
62
+ def conf( opt, value = nil )
63
+ if value
64
+ @conf[ opt ] = value
65
+ else
66
+ @conf[ opt ]
67
+ end
68
+ end
69
+
70
+
71
+ # Return list of included (local) header files. Can be used e.g. for
72
+ # c-to-h file dependence.
73
+ #
74
+ # @return [Array<HeaderFile>] Headers.
75
+ def headers
76
+ @localHeader
77
+ end
78
+
79
+
80
+ # Return list of defined functions. Can be used e.g. to
81
+ # generate function declarations to a header file
82
+ # (automatically).
83
+ #
84
+ # @return [Array<HeaderFile>] Functions.
85
+ def funcdefs
86
+ @funcdefs
87
+ end
88
+
89
+
90
+ def funcalls
91
+ @funcalls
92
+ end
93
+
94
+
95
+ # Return true if file name is for a local header.
96
+ def isLocalHeader?( file )
97
+ if file[0] != '/' && /\.h$/.match( file )
98
+ true
99
+ else
100
+ false
101
+ end
102
+ end
103
+
104
+
105
+ # Parse c-file.
106
+ #
107
+ # @param headerPath [String] Path for system header lookup.
108
+ def parse( headerPath = @headerPath )
109
+
110
+ index = FFI::Clang::Index.new
111
+ translation_unit = index.parse_translation_unit( @name, headerPath )
112
+ cursor = translation_unit.cursor
113
+
114
+ # Get list of included local headers.
115
+ translation_unit.inclusions do |header|
116
+ if isLocalHeader? header
117
+ @localHeader[ header ] = HeaderFile.new( header )
118
+ end
119
+ end
120
+
121
+ # Recursively travel the c-file hierarchy to detect
122
+ # function definitions.
123
+ cursor.visit_children do |cursor, parent|
124
+
125
+ if cursor.kind == :cursor_function
126
+
127
+ # Check that function is in the file that is being
128
+ # analysed. Might also be from an included header.
129
+ if ( @conf[:mainonly] == false ) || cursor.location.from_main_file?
130
+
131
+ f = Function.new( cursor.spelling, cursor.variadic? )
132
+ f.setReturnType( cursor.result_type.spelling )
133
+
134
+ # Get argument list.
135
+ cursor.visit_children do |cursor, parent|
136
+
137
+ case cursor.kind
138
+
139
+ when :cursor_parm_decl
140
+ f.addArgument( cursor.spelling, cursor.type.spelling )
141
+
142
+ else
143
+ # puts cursor.kind
144
+ true
145
+
146
+ end
147
+
148
+ next :continue
149
+ end
150
+
151
+
152
+ # Mark function complete and add to list.
153
+ @funcdefs[ f.name ] = f.done
154
+
155
+ if @conf[:defsonly]
156
+ # Don't recurse anymore.
157
+ next :continue
158
+ else
159
+ next :recurse
160
+ end
161
+
162
+ else
163
+
164
+ next :continue
165
+
166
+ end
167
+
168
+ elsif cursor.kind == :cursor_call_expr
169
+
170
+
171
+ # if cursor.location.from_main_file?
172
+ f = FunCall.new( cursor.spelling )
173
+ @funcalls[ f.name ] = f
174
+ # end
175
+
176
+ next :recurse
177
+
178
+ else
179
+
180
+ # Non-functions are not interesting.
181
+ next :recurse
182
+
183
+ end
184
+
185
+ end
186
+ end
187
+
188
+
189
+ # Display c-file content.
190
+ def display
191
+ puts "File: #{@name}"
192
+ puts " Includes:"
193
+ @localHeader.each_value do |i|
194
+ puts " #{i.name} | #{i.path}"
195
+ end
196
+ puts " Functions:"
197
+ @funcdefs.each_value do |f|
198
+ puts " #{f.declaration}"
199
+ end
200
+ end
201
+
202
+
203
+ # Show raw content of c-file.
204
+ def dump( headerPath = @headerPath )
205
+ index = FFI::Clang::Index.new
206
+ translation_unit = index.parse_translation_unit( @name, headerPath )
207
+ cursor = translation_unit.cursor
208
+ cursor.visit_children do |cursor, parent|
209
+ puts "#{cursor.kind} #{cursor.spelling}"
210
+ next :recurse
211
+ end
212
+ end
213
+
214
+
215
+ end
216
+
217
+
218
+ # Included local header.
219
+ class HeaderFile
220
+
221
+ # File name.
222
+ attr_reader :name
223
+
224
+ # File path.
225
+ attr_reader :path
226
+
227
+ # Initialize.
228
+ def initialize( path )
229
+ @name = File.basename( path )
230
+ @path = path
231
+ end
232
+
233
+ end
234
+
235
+
236
+ # Defined function.
237
+ class Function
238
+
239
+ # Func name.
240
+ attr_reader :name
241
+
242
+ # Variadic (end with ellipsis).
243
+ attr_reader :variadic
244
+
245
+
246
+ # Initialize function object. Default return type to void.
247
+ #
248
+ # @param name [String] Func name.
249
+ def initialize( name, variadic = false )
250
+ @name = name
251
+ @variadic = variadic
252
+ @args = {}
253
+ @returnType = 'void'
254
+ end
255
+
256
+
257
+ # Set function return type.
258
+ def setReturnType( type )
259
+ @returnType = type
260
+ end
261
+
262
+
263
+ # Add argument to functions argument list.
264
+ def addArgument( name, type )
265
+ @args[ name ] = type
266
+ end
267
+
268
+
269
+ # Close function defition. If argument list is empty, then arg
270
+ # list contains only void.
271
+ def done
272
+ if @variadic
273
+ @args[ nil ] = '...'
274
+ end
275
+
276
+ if @args.empty?
277
+ @args = { nil => 'void' }
278
+ end
279
+ self
280
+ end
281
+
282
+
283
+ # Get argument declarations String presentation.
284
+ def argDecl( name )
285
+ if name
286
+ # Has type.
287
+ "#{@args[ name ]} #{name}"
288
+ else
289
+ # Void/variadic.
290
+ @args[ name ]
291
+ end
292
+ end
293
+
294
+
295
+ # Return functions declation as String.
296
+ def declaration
297
+ "#{@returnType} #{@name}( #{(@args.keys.map { |k| argDecl(k) }).join(', ')} );"
298
+ end
299
+
300
+ end
301
+
302
+ class FunCall
303
+ # Func name.
304
+ attr_reader :name
305
+
306
+ def initialize( name )
307
+ @name = name
308
+ end
309
+ end
310
+
311
+ end
@@ -1,5 +1,5 @@
1
1
  module Crun
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  def Crun.version
4
4
  Crun::VERSION
5
5
  end
@@ -0,0 +1,12 @@
1
+ Greeting #1!
2
+ Greeting #2!
3
+ Greeting #3!
4
+ Greeting #4!
5
+ Greeting #5!
6
+ Greeting #6!
7
+ Greeting #7!
8
+ Greeting #8!
9
+ Greeting #9!
10
+ Greeting #10!
11
+ Greeting #11!
12
+ Greeting #12!
@@ -0,0 +1,12 @@
1
+ Greeting #1!
2
+ Greeting #2!
3
+ Greeting #3!
4
+ Greeting #4!
5
+ Greeting #5!
6
+ Greeting #6!
7
+ Greeting #7!
8
+ Greeting #8!
9
+ Greeting #9!
10
+ Greeting #10!
11
+ Greeting #11!
12
+ Greeting #12!
@@ -39,5 +39,6 @@ class CrunTest < Test::Unit::TestCase
39
39
  def test_override2() runTest( "override2", "-f ../examples/greeting.c -o \"progopts:.-c 13\"" ); end
40
40
  def test_override3() runTest( "override3", "-f ../examples/greeting.c -o \"progopts:+-c 13\"" ); end
41
41
  def test_template() runTest( "template", "-f ../examples/greeting.c -o \"progopts:+-c 13\" -t" ); end
42
+ def test_autoheader() runTest( "autoheader", "-a -f ../examples/greeting_noheader.c" ); end
42
43
 
43
44
  end
metadata CHANGED
@@ -1,19 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tero Isannainen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-22 00:00:00.000000000 Z
11
+ date: 2017-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: como
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
17
20
  - - ">="
18
21
  - !ruby/object:Gem::Version
19
22
  version: 0.2.0
@@ -21,9 +24,32 @@ dependencies:
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
24
30
  - - ">="
25
31
  - !ruby/object:Gem::Version
26
32
  version: 0.2.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: ffi-clang
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.3'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.3.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.3'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.3.0
27
53
  description: |-
28
54
  Crun is an utility for compiling and running C-programs straight from
29
55
  C source files. Crun supports compile-run and compile-debug flows.
@@ -46,15 +72,19 @@ files:
46
72
  - bin/crun
47
73
  - examples/crun_conf.rb
48
74
  - examples/greeting.c
75
+ - examples/greeting_noheader.c
49
76
  - examples/hello.c
50
77
  - examples/sizeof.c
78
+ - lib/parsec.rb
51
79
  - lib/version.rb
80
+ - test/golden/autoheader.txt
52
81
  - test/golden/basic.txt
53
82
  - test/golden/conf.txt
54
83
  - test/golden/override.txt
55
84
  - test/golden/override2.txt
56
85
  - test/golden/override3.txt
57
86
  - test/golden/template.txt
87
+ - test/result/autoheader.txt
58
88
  - test/result/basic.txt
59
89
  - test/result/conf.txt
60
90
  - test/result/override.txt