diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/lua/lua.make | 7 | ||||
-rw-r--r-- | apps/plugins/lua/rocklib.c | 137 | ||||
-rwxr-xr-x | apps/plugins/lua/settings_helper.pl | 397 |
3 files changed, 540 insertions, 1 deletions
diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make index a464bddace..ef9705a63d 100644 --- a/apps/plugins/lua/lua.make +++ b/apps/plugins/lua/lua.make | |||
@@ -35,11 +35,16 @@ else | |||
35 | ROCKS += $(LUA_BUILDDIR)/lua.rock | 35 | ROCKS += $(LUA_BUILDDIR)/lua.rock |
36 | endif | 36 | endif |
37 | 37 | ||
38 | $(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_INCLUDELIST) | 38 | $(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/settings.lua $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_INCLUDELIST) |
39 | 39 | ||
40 | $(LUA_BUILDDIR)/actions.lua: $(LUA_OBJ) $(LUA_SRCDIR)/action_helper.pl | 40 | $(LUA_BUILDDIR)/actions.lua: $(LUA_OBJ) $(LUA_SRCDIR)/action_helper.pl |
41 | $(call PRINTS,GEN $(@F))$(CC) $(PLUGINFLAGS) $(INCLUDES) -E $(APPSDIR)/plugins/lib/pluginlib_actions.h | $(LUA_SRCDIR)/action_helper.pl > $(LUA_BUILDDIR)/actions.lua | 41 | $(call PRINTS,GEN $(@F))$(CC) $(PLUGINFLAGS) $(INCLUDES) -E $(APPSDIR)/plugins/lib/pluginlib_actions.h | $(LUA_SRCDIR)/action_helper.pl > $(LUA_BUILDDIR)/actions.lua |
42 | 42 | ||
43 | $(LUA_BUILDDIR)/settings.lua: $(LUA_OBJ) $(LUA_SRCDIR)/settings_helper.pl | ||
44 | $(SILENT)$(CC) $(INCLUDES) -E $(TARGET) $(CFLAGS) -include plugin.h -include cuesheet.h - < /dev/null | $(LUA_SRCDIR)/settings_helper.pl | \ | ||
45 | $(CC) $(INCLUDES) $(TARGET) $(CFLAGS) -S -x c -include config.h -include plugin.h -o $(LUA_BUILDDIR)/settings_helper.s - | ||
46 | $(call PRINTS,GEN $(@F))$(LUA_SRCDIR)/settings_helper.pl < $(LUA_BUILDDIR)/settings_helper.s > $(LUA_BUILDDIR)/settings.lua | ||
47 | |||
43 | HOST_INCLUDES := $(filter-out %/libc/include,$(INCLUDES)) | 48 | HOST_INCLUDES := $(filter-out %/libc/include,$(INCLUDES)) |
44 | $(LUA_BUILDDIR)/buttons.lua: $(LUA_OBJ) $(LUA_SRCDIR)/button_helper.pl | 49 | $(LUA_BUILDDIR)/buttons.lua: $(LUA_OBJ) $(LUA_SRCDIR)/button_helper.pl |
45 | $(SILENT)$(CC) $(INCLUDES) -dM -E -include button-target.h - < /dev/null | $(LUA_SRCDIR)/button_helper.pl | $(HOSTCC) -fno-builtin $(HOST_INCLUDES) -x c -o $(LUA_BUILDDIR)/button_helper - | 50 | $(SILENT)$(CC) $(INCLUDES) -dM -E -include button-target.h - < /dev/null | $(LUA_SRCDIR)/button_helper.pl | $(HOSTCC) -fno-builtin $(HOST_INCLUDES) -x c -o $(LUA_BUILDDIR)/button_helper - |
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index a6a23f3381..6c96f37a94 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c | |||
@@ -564,6 +564,137 @@ RB_WRAP(strncasecmp) | |||
564 | return 1; | 564 | return 1; |
565 | } | 565 | } |
566 | 566 | ||
567 | static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize) | ||
568 | { | ||
569 | intptr_t offset = (intptr_t) luaL_optint(L, 1, 0); | ||
570 | size_t size = (size_t) luaL_optint(L, 2, maxsize); | ||
571 | size_t written; | ||
572 | int type = lua_type(L, 3); | ||
573 | |||
574 | if(offset < 0) | ||
575 | { | ||
576 | /* allows pointer within structure to be calculated offset */ | ||
577 | offset = -(address + offset); | ||
578 | size = (size_t) maxsize - offset; | ||
579 | } | ||
580 | |||
581 | luaL_argcheck(L, ((uintptr_t) offset) + size <= maxsize, 2, ERR_IDX_RANGE); | ||
582 | |||
583 | char *mem = (char*) address + ((uintptr_t) offset); | ||
584 | const void *value = NULL; | ||
585 | |||
586 | lua_Integer var_luaint; | ||
587 | #ifdef UINT64_MAX | ||
588 | int64_t var_64; | ||
589 | #endif | ||
590 | int32_t var_32; | ||
591 | int16_t var_16; | ||
592 | int8_t var_8; | ||
593 | bool var_bool; | ||
594 | |||
595 | switch(type) | ||
596 | { | ||
597 | case LUA_TSTRING: | ||
598 | { | ||
599 | size_t len; | ||
600 | const char* str = lua_tolstring (L, 3, &len); | ||
601 | |||
602 | luaL_argcheck(L, len + 1 <= size, 3, ERR_DATA_OVF); | ||
603 | size = len + 1; /* include \0 */ | ||
604 | value = str; | ||
605 | break; | ||
606 | } | ||
607 | case LUA_TBOOLEAN: | ||
608 | { | ||
609 | var_bool = (bool) lua_toboolean(L, 3); | ||
610 | value = &var_bool; | ||
611 | break; | ||
612 | } | ||
613 | case LUA_TNUMBER: | ||
614 | { | ||
615 | var_luaint = lua_tointeger(L, 3); | ||
616 | switch(size) | ||
617 | { | ||
618 | case sizeof(var_8): | ||
619 | var_8 = (int8_t) var_luaint; | ||
620 | value = &var_8; | ||
621 | break; | ||
622 | case sizeof(var_16): | ||
623 | var_16 = (int16_t) var_luaint; | ||
624 | value = &var_16; | ||
625 | break; | ||
626 | case sizeof(var_32): | ||
627 | var_32 = (int32_t) var_luaint; | ||
628 | value = &var_32; | ||
629 | break; | ||
630 | #ifdef UINT64_MAX | ||
631 | case sizeof(var_64): | ||
632 | var_64 = (int64_t) var_luaint; | ||
633 | value = &var_64; | ||
634 | break; | ||
635 | #endif | ||
636 | } /* switch size */ | ||
637 | break; | ||
638 | } | ||
639 | case LUA_TNIL: | ||
640 | case LUA_TNONE: /* reader */ | ||
641 | { | ||
642 | luaL_Buffer b; | ||
643 | luaL_buffinit(L, &b); | ||
644 | while(size > 0) | ||
645 | { | ||
646 | written = MIN(LUAL_BUFFERSIZE, size); | ||
647 | luaL_addlstring (&b, mem, written); | ||
648 | mem += written; | ||
649 | size -= written; | ||
650 | } | ||
651 | |||
652 | luaL_pushresult(&b); | ||
653 | return 1; | ||
654 | } | ||
655 | |||
656 | default: | ||
657 | break; | ||
658 | } /* switch type */ | ||
659 | |||
660 | /* writer */ | ||
661 | luaL_argcheck(L, value != NULL, 3, "Unknown Type"); | ||
662 | rb->memcpy(mem, value, size); | ||
663 | lua_pushinteger(L, 1); | ||
664 | |||
665 | return 1; | ||
666 | } | ||
667 | |||
668 | RB_WRAP(global_status) | ||
669 | { | ||
670 | const uintptr_t address = (uintptr_t) rb->global_status; | ||
671 | const size_t maxsize = sizeof(struct system_status); | ||
672 | return mem_read_write(L, address, maxsize); | ||
673 | } | ||
674 | |||
675 | RB_WRAP(global_settings) | ||
676 | { | ||
677 | const uintptr_t address = (uintptr_t) rb->global_settings; | ||
678 | const size_t maxsize = sizeof(struct user_settings); | ||
679 | return mem_read_write(L, address, maxsize); | ||
680 | } | ||
681 | |||
682 | RB_WRAP(audio_next_track) | ||
683 | { | ||
684 | lua_settop(L, 2); /* no writes allowed */ | ||
685 | const uintptr_t address = (uintptr_t) rb->audio_next_track(); | ||
686 | const size_t maxsize = sizeof(struct mp3entry); | ||
687 | return mem_read_write(L, address, maxsize); | ||
688 | } | ||
689 | |||
690 | RB_WRAP(audio_current_track) | ||
691 | { | ||
692 | lua_settop(L, 2); /* no writes allowed */ | ||
693 | const uintptr_t address = (uintptr_t) rb->audio_current_track(); | ||
694 | const size_t maxsize = sizeof(struct mp3entry); | ||
695 | return mem_read_write(L, address, maxsize); | ||
696 | } | ||
697 | |||
567 | #define RB_FUNC(func) {#func, rock_##func} | 698 | #define RB_FUNC(func) {#func, rock_##func} |
568 | #define RB_ALIAS(name, func) {name, rock_##func} | 699 | #define RB_ALIAS(name, func) {name, rock_##func} |
569 | static const luaL_Reg rocklib[] = | 700 | static const luaL_Reg rocklib[] = |
@@ -625,6 +756,12 @@ static const luaL_Reg rocklib[] = | |||
625 | RB_FUNC(utf8encode), | 756 | RB_FUNC(utf8encode), |
626 | RB_FUNC(strncasecmp), | 757 | RB_FUNC(strncasecmp), |
627 | 758 | ||
759 | /* ROCKBOX SETTINGS / INFO */ | ||
760 | RB_FUNC(global_status), | ||
761 | RB_FUNC(global_settings), | ||
762 | RB_FUNC(audio_next_track), | ||
763 | RB_FUNC(audio_current_track), | ||
764 | |||
628 | {NULL, NULL} | 765 | {NULL, NULL} |
629 | }; | 766 | }; |
630 | #undef RB_FUNC | 767 | #undef RB_FUNC |
diff --git a/apps/plugins/lua/settings_helper.pl b/apps/plugins/lua/settings_helper.pl new file mode 100755 index 0000000000..215d3a2a3c --- /dev/null +++ b/apps/plugins/lua/settings_helper.pl | |||
@@ -0,0 +1,397 @@ | |||
1 | #!/usr/bin/env perl | ||
2 | ############################################################################ | ||
3 | # __________ __ ___. | ||
4 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | # \/ \/ \/ \/ \/ | ||
9 | # $Id$ | ||
10 | # | ||
11 | # Copyright (C) 2018 William Wilgus | ||
12 | # | ||
13 | # All files in this archive are subject to the GNU General Public License. | ||
14 | # See the file COPYING in the source tree root for full license agreement. | ||
15 | # | ||
16 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
17 | # KIND, either express or implied. | ||
18 | # | ||
19 | ############################################################################ | ||
20 | |||
21 | # Extracts members from c struct | ||
22 | # places them in a lua array 'member = {offset,size,"type"}' | ||
23 | # requires two passes | ||
24 | # first pass outputs a c file that shall be compiled with the -S option | ||
25 | # second pass extracts the member, offset, size, type from the assembly | ||
26 | |||
27 | my $svnrev = '$Revision$'; | ||
28 | my $helper_name = 'LUA_RB_SETTINGS_H_HELPER'; | ||
29 | |||
30 | ############# configuration ############# | ||
31 | my @sections = ( | ||
32 | '', | ||
33 | 'struct system_status', | ||
34 | 'struct user_settings', | ||
35 | 'struct replaygain_settings', | ||
36 | 'struct eq_band_setting', | ||
37 | 'struct compressor_settings', | ||
38 | 'struct mp3_enc_config', | ||
39 | '', | ||
40 | 'struct mp3entry', | ||
41 | 'struct mp3_albumart', | ||
42 | 'struct embedded_cuesheet', | ||
43 | #'struct cuesheet', | ||
44 | #'struct cue_track_info', | ||
45 | ); | ||
46 | |||
47 | my @sections_lua = ( | ||
48 | 'rb.system', | ||
49 | 'rb.system.global_status', | ||
50 | 'rb.system.global_settings', | ||
51 | 'rb.system.replaygain_settings', | ||
52 | 'rb.system.eq_band_setting', | ||
53 | 'rb.system.compressor_settings', | ||
54 | 'rb.system.mp3_enc_config', | ||
55 | 'rb.metadata', | ||
56 | 'rb.metadata.mp3_entry', | ||
57 | 'rb.metadata.mp3_albumart', | ||
58 | 'rb.metadata.embedded_cuesheet', | ||
59 | #'rb.metadata.cuesheet', | ||
60 | #'rb.metadata.cue_track_info', | ||
61 | ); | ||
62 | |||
63 | # structs will have their dependencies included automagically | ||
64 | my @includes = (); | ||
65 | |||
66 | my $section_lua_suffix = ''; | ||
67 | |||
68 | my %replace_type_prefix = ( | ||
69 | unsigned => 'u_', | ||
70 | signed => '', | ||
71 | struct => 's_', | ||
72 | const => 'const_', | ||
73 | enum => 'e_', | ||
74 | '#pointer#' => 'ptr_', | ||
75 | ); | ||
76 | |||
77 | my %replace_type = ( | ||
78 | int => 'i', | ||
79 | uint => 'u_i', | ||
80 | long => 'l', | ||
81 | char => 'c', | ||
82 | bool => 'b', | ||
83 | double => 'd', | ||
84 | '#string#' => 'str', | ||
85 | ); | ||
86 | |||
87 | ############# internal ############# | ||
88 | my @section_count = (); #variables found | ||
89 | my @section_found = (); #{} bracket matches | ||
90 | my @section_lists = (); #variable declarations | ||
91 | my @section_asm_regex = (); | ||
92 | my @section_begin_regex = (); | ||
93 | |||
94 | my $header = ''; | ||
95 | my $array_marker = '_typeisarray_'; | ||
96 | my $pointer_marker = '_typeisptr_'; | ||
97 | my $current_include; | ||
98 | |||
99 | ############# precompile regex for speed ############# | ||
100 | my $array_mark_regex = qr/^.*${array_marker}$/; | ||
101 | my $pointer_mark_regex = qr/^(.*)${pointer_marker}.*$/; | ||
102 | |||
103 | my $incl_regex = qr/^.*\".+\/(.+\.h)\".*$/; | ||
104 | my $extern_regex = qr/^extern\b.*$/; | ||
105 | |||
106 | #type var ????; | ||
107 | my $decl_regex = qr/^(.+?\s.+;)/; | ||
108 | my $typevar_regex = qr/\W*(?<type>.*?)\W*(?<var>[^\s\[]+)(?<arr>)\W*;/; | ||
109 | my$typevar_array_regex = qr/\W*(?<type>.*?)\W*(?<var>[^\s\[]+)\W*(?<arr>\[.+\]).*;/; | ||
110 | |||
111 | #.."section",.."member"..=..offset,..size,..type,..arrayct | ||
112 | my $asm_regex = qr/.*?,.*?(\".+?\".*?=.*?,.+?,.+?\".+\".*?,.*);/; | ||
113 | my $asmMOST_regex = qr/\"(?<member>.+)\"=(?<offset>\d+),(?<size>\d+),\"(?<type>.+)\",(?<arr>\d+).*/; | ||
114 | |||
115 | for(my $i = 0; $i < @sections; $i++) | ||
116 | { | ||
117 | $section_asm_regex[$i] = qr/\"$sections[$i]\"${asm_regex}/; | ||
118 | $section_begin_regex[$i] = qr/^$sections[$i]\b\s*+[^\*;]*$/; | ||
119 | $section_count[$i] = 0; | ||
120 | $section_found[$i] = 0; | ||
121 | $section_lists[$i] = ''; | ||
122 | } | ||
123 | |||
124 | my $section_end_regex = qr/}\s*;.*$/; | ||
125 | |||
126 | ####################################################### | ||
127 | #extract all the variables within the structs(sections) | ||
128 | ####################################################### | ||
129 | while(my $line = <STDIN>) | ||
130 | { | ||
131 | next if($line =~ /^\s+$/); | ||
132 | |||
133 | chomp($line); | ||
134 | |||
135 | if($header) #second pass | ||
136 | { | ||
137 | for(my $i = 0; $i < @sections; $i++) | ||
138 | { | ||
139 | next if(!$sections[$i]); | ||
140 | |||
141 | if($line =~ $section_asm_regex[$i]) | ||
142 | { | ||
143 | $section_lists[$i] .= $1.'@'; | ||
144 | $section_count[$i]++; | ||
145 | last; | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | elsif($line =~ s/$helper_name\W*//) #is this the second pass? | ||
150 | { | ||
151 | $header = $line; | ||
152 | #warn $header."\n"; | ||
153 | for(my $i = 0; $i < @sections; $i++) | ||
154 | { | ||
155 | @section_lists[$i] = ''; | ||
156 | @section_count[$i] = 0; | ||
157 | } | ||
158 | } | ||
159 | else #first pass | ||
160 | { | ||
161 | if($line =~ $incl_regex){$current_include = $1; next;} | ||
162 | elsif($line =~ $extern_regex){next;} | ||
163 | |||
164 | for(my $i = 0; $i < @sections; $i++) | ||
165 | { | ||
166 | next if(!$sections[$i]); | ||
167 | |||
168 | if($section_found[$i] > 0) | ||
169 | { | ||
170 | # variable declaration? | ||
171 | if($line =~ $decl_regex) | ||
172 | { | ||
173 | $section_lists[$i] .= $1.'@'; | ||
174 | $section_count[$i]++; | ||
175 | } | ||
176 | |||
177 | # struct end? | ||
178 | if($line =~ $section_end_regex) | ||
179 | { | ||
180 | $section_found[$i]--; | ||
181 | } | ||
182 | last; | ||
183 | } | ||
184 | elsif($line =~ $section_begin_regex[$i]) # struct begin? | ||
185 | { | ||
186 | if($current_include) | ||
187 | { | ||
188 | push (@includes, $current_include); | ||
189 | $current_include = ''; | ||
190 | } | ||
191 | $section_found[$i]++; | ||
192 | $section_lists[$i] = ''; | ||
193 | $section_count[$i] = 0; | ||
194 | last; | ||
195 | } | ||
196 | } | ||
197 | }#else | ||
198 | } | ||
199 | |||
200 | for(my $i = 0; $i < @sections; $i++) | ||
201 | { | ||
202 | if($section_found[$i]) | ||
203 | { | ||
204 | warn "$0 Warning formatting error in: $sections[$i]\n"; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | sub Extract_Variable { | ||
209 | #extracts the member, offset, size, and type from the include file | ||
210 | my $sinput = $_[0]; | ||
211 | my ($type, $var, $arr); | ||
212 | |||
213 | $sinput =~ s{\s*\*\s*}{${pointer_marker}}gx; | ||
214 | if($sinput =~ $typevar_array_regex) #arrays | ||
215 | { | ||
216 | $type = $+{type}; | ||
217 | $var = $+{var}; | ||
218 | $arr = $+{var}; | ||
219 | if($sinput =~ s/\bchar\b//){$type = $replace_type{'#string#'};} | ||
220 | else{$type .= ${array_marker};} #for identification of array .. stripped later | ||
221 | } | ||
222 | elsif($sinput =~ $typevar_regex) | ||
223 | { | ||
224 | $type = $+{type}; | ||
225 | $var = $+{var}; | ||
226 | $arr = $+{var}; | ||
227 | } | ||
228 | else { return ('', '', ''); } | ||
229 | |||
230 | $type =~ s/^(unsigned|signed|struct)/$replace_type_prefix{$1}/x; | ||
231 | $type =~ s/\b(const|enum)\b/$replace_type_prefix{$1}/gx; | ||
232 | $type =~ s/^(?:.?+)(bool)\b/$replace_type{lc $1}/ix; | ||
233 | $type =~ s/^(uint|int)(?:\d\d_t)\b/$replace_type{lc $1}/ix; | ||
234 | $type =~ s/\b(int|long|char|double)(${array_marker}.*)?\b/$replace_type{$1}$2/; | ||
235 | $type =~ s{\s+}{}gx; | ||
236 | |||
237 | $var =~ s{[^\w\d_]+}{}gx; #strip non conforming chars | ||
238 | |||
239 | $arr =~ s{[^\[\d\]]+}{}gx; | ||
240 | |||
241 | return ($type, $var, $arr); | ||
242 | } | ||
243 | |||
244 | sub Print_Variable { | ||
245 | #prints the member, offset, size, and type from the assembly file | ||
246 | my $sinput = $_[0]; | ||
247 | my ($member, $offset, $size, $type, $arr); | ||
248 | |||
249 | $sinput =~ s{[^\w\d_,=\"\*]+}{}gx; | ||
250 | if($sinput =~ $asmMOST_regex) | ||
251 | { | ||
252 | $member = $+{member}; | ||
253 | $offset = $+{offset}; | ||
254 | $size = $+{size}; | ||
255 | $type = $+{type}; | ||
256 | $arr = $+{arr}; | ||
257 | |||
258 | if($type =~ /^(.*)${array_marker}$/) #strip array marker add [n] | ||
259 | { | ||
260 | $type = sprintf('%s[%d]', $1, $arr); | ||
261 | } | ||
262 | |||
263 | printf "\t%s = {0x%x, %d, \"%s\"},\n", $member, $offset, $size, $type; | ||
264 | return 1; | ||
265 | } | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | if($header) #output sections to lua file | ||
270 | { | ||
271 | print "-- Don't change this file!\n"; | ||
272 | printf "-- It is automatically generated %s\n", $svnrev; | ||
273 | print "-- member = {offset, size, \"type\"}\n\n"; | ||
274 | |||
275 | print "--"; | ||
276 | foreach my $key (sort(keys %replace_type_prefix)) { | ||
277 | print $key, '= \'', $replace_type_prefix{$key}, '\', '; | ||
278 | } | ||
279 | print "\n--"; | ||
280 | foreach my $key (sort(keys %replace_type)) { | ||
281 | print $key, '= \'', $replace_type{$key}, '\', '; | ||
282 | } | ||
283 | print "\n\n"; | ||
284 | |||
285 | for(my $i = 0; $i < @sections_lua; $i++) | ||
286 | { | ||
287 | if($sections_lua[$i]) | ||
288 | { | ||
289 | print "$sections_lua[$i]$section_lua_suffix = {\n"; | ||
290 | |||
291 | my @members=split('@', $section_lists[$i]); | ||
292 | $section_lists[$i] = ''; | ||
293 | |||
294 | foreach my $memb(@members) | ||
295 | { | ||
296 | $section_count[$i] -= Print_Variable($memb); | ||
297 | } | ||
298 | |||
299 | print "}\n\n"; | ||
300 | |||
301 | if($sections[$i] && $section_count[$i] ne 0) | ||
302 | { | ||
303 | warn "$0 Warning: Failed to extract '$sections[$i]'\n"; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | #my ($user,$system,$cuser,$csystem) = times; | ||
308 | #warn "Pass2 ".$user." ".$system." ".$cuser." ".$csystem."\n"; | ||
309 | exit; | ||
310 | } | ||
311 | |||
312 | #else output sections to .c file | ||
313 | my $header = join(", ", $helper_name, @sections); | ||
314 | my $print_variable = 'PRINT_M_O_S_T'; | ||
315 | my $print_array = 'PRINT_ARRAY_M_O_S_T'; | ||
316 | my $emit_asm = 'ASM_EMIT_M_O_S_T'; | ||
317 | |||
318 | foreach my $incl(@includes) | ||
319 | { | ||
320 | printf "#include \"%s\"\n", $incl; | ||
321 | } | ||
322 | |||
323 | print <<EOF | ||
324 | |||
325 | #include <stddef.h> /* offsetof */ | ||
326 | #include <stdbool.h> | ||
327 | |||
328 | /* (ab)uses the compiler to emit member offset and size to asm comments */ | ||
329 | /* GAS supports C-style comments in asm files other compilers may not */ | ||
330 | /* "NAME", "MEMBER" = ?OFFSET, ?SIZE, "TYPE, ?ARRAYCT"; | ||
331 | NOTE: ? may differ between machines */ | ||
332 | |||
333 | #undef ${emit_asm} | ||
334 | #define ${emit_asm}(name, member, type, offset, size, elems) asm volatile\\ | ||
335 | ("/* "#name ", " #member " = %0, %1, " #type ", %2; */\\n" : : \\ | ||
336 | "n"(offset), "n"(size), "n"(elems)) | ||
337 | |||
338 | #undef ${print_variable} | ||
339 | #define ${print_variable}(name, member, value, type) ${emit_asm}(#name, \\ | ||
340 | #member, #type, offsetof(name, member), sizeof(value), 0) | ||
341 | |||
342 | #undef ${print_array} | ||
343 | #define ${print_array}(name, member, value, type) ${emit_asm}(#name, \\ | ||
344 | #member, #type, offsetof(name, member), sizeof(value), sizeof(value)/sizeof(value[0])) | ||
345 | |||
346 | int main(void) | ||
347 | { | ||
348 | |||
349 | /* GAS supports C-style comments in asm files other compilers may not */ | ||
350 | /* This header identifies assembler output for second pass */ | ||
351 | asm volatile("/* $header; */"); | ||
352 | |||
353 | EOF | ||
354 | ; | ||
355 | my $section_prefix = "section_"; | ||
356 | my $format_asm = " %s(%s, %s, ${section_prefix}%d.%s, %s);\n"; | ||
357 | |||
358 | |||
359 | for(my $i = 0; $i < @sections; $i++) | ||
360 | { | ||
361 | if($sections[$i] && $section_lists[$i]) | ||
362 | { | ||
363 | printf "%s %s%d;\n", $sections[$i], $section_prefix, $i; #create variable for each section | ||
364 | my @members=split('@', $section_lists[$i]); | ||
365 | $section_lists[$i] = ''; | ||
366 | |||
367 | foreach my $memb(@members) | ||
368 | { | ||
369 | my ($type, $var, $arr) = Extract_Variable($memb); | ||
370 | my $call = ${print_variable}; | ||
371 | |||
372 | if($var =~ $pointer_mark_regex) #strip pointer marker | ||
373 | { | ||
374 | $type = $type.$1; | ||
375 | $var =~ s{.*${pointer_marker}}{}gx; | ||
376 | $type = $replace_type_prefix{'#pointer#'}.$type; | ||
377 | } | ||
378 | |||
379 | if($type && $var) | ||
380 | { | ||
381 | if($type =~ $array_mark_regex){$call = ${print_array};} | ||
382 | printf $format_asm, $call, $sections[$i], $var, $i, $var, $type; | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | print <<EOF | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | EOF | ||
393 | ; | ||
394 | |||
395 | #my ($user,$system,$cuser,$csystem) = times; | ||
396 | #warn "Pass1 ".$user." ".$system." ".$cuser." ".$csystem."\n"; | ||
397 | |||