riscos-stronghelp 0.3.16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- riscos_stronghelp-0.3.16/PKG-INFO +46 -0
- riscos_stronghelp-0.3.16/README.md +27 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp/__init__.py +0 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp/__main__.py +142 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp/format.py +273 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp.egg-info/PKG-INFO +46 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp.egg-info/SOURCES.txt +10 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp.egg-info/dependency_links.txt +1 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp.egg-info/entry_points.txt +3 -0
- riscos_stronghelp-0.3.16/riscos_stronghelp.egg-info/top_level.txt +1 -0
- riscos_stronghelp-0.3.16/setup.cfg +4 -0
- riscos_stronghelp-0.3.16/setup.py +47 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: riscos_stronghelp
|
|
3
|
+
Version: 0.3.16
|
|
4
|
+
Summary: Extract RISC OS StrongHelp manuals
|
|
5
|
+
Home-page: https://github.com/gerph/riscos-stronghelp-python
|
|
6
|
+
Author: Charles Ferguson
|
|
7
|
+
Author-email: gerph@gerph.org
|
|
8
|
+
License: MIT
|
|
9
|
+
Description: # Python StrongHelp reader
|
|
10
|
+
|
|
11
|
+
This repository contains a reader for the RISC OS StrongHelp manual image format.
|
|
12
|
+
|
|
13
|
+
The Python module is able to be used to parse the format and return the files
|
|
14
|
+
which are present. The module can also be used as a command line tool to
|
|
15
|
+
extract the files to a unix file system.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
The tool for extracting StrongHelp files can be installed manually
|
|
21
|
+
using this repository or through PyPI. To install, use:
|
|
22
|
+
|
|
23
|
+
pip3 install riscos_stronghelp
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Command line
|
|
27
|
+
|
|
28
|
+
At the command line the extraction tool may be used with the
|
|
29
|
+
supplied shell command:
|
|
30
|
+
|
|
31
|
+
riscos-shextract [--extract-dir <directory>] <stronghelp-file>
|
|
32
|
+
|
|
33
|
+
Or to list files:
|
|
34
|
+
|
|
35
|
+
riscos-shextract --list <stronghelp-file>
|
|
36
|
+
|
|
37
|
+
Keywords: riscos
|
|
38
|
+
Platform: UNKNOWN
|
|
39
|
+
Classifier: Development Status :: 4 - Beta
|
|
40
|
+
Classifier: Intended Audience :: Developers
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
43
|
+
Classifier: Programming Language :: Python :: 3
|
|
44
|
+
Classifier: Operating System :: OS Independent
|
|
45
|
+
Requires-Python: >=2.7
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python StrongHelp reader
|
|
2
|
+
|
|
3
|
+
This repository contains a reader for the RISC OS StrongHelp manual image format.
|
|
4
|
+
|
|
5
|
+
The Python module is able to be used to parse the format and return the files
|
|
6
|
+
which are present. The module can also be used as a command line tool to
|
|
7
|
+
extract the files to a unix file system.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
The tool for extracting StrongHelp files can be installed manually
|
|
13
|
+
using this repository or through PyPI. To install, use:
|
|
14
|
+
|
|
15
|
+
pip3 install riscos_stronghelp
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Command line
|
|
19
|
+
|
|
20
|
+
At the command line the extraction tool may be used with the
|
|
21
|
+
supplied shell command:
|
|
22
|
+
|
|
23
|
+
riscos-shextract [--extract-dir <directory>] <stronghelp-file>
|
|
24
|
+
|
|
25
|
+
Or to list files:
|
|
26
|
+
|
|
27
|
+
riscos-shextract --list <stronghelp-file>
|
|
File without changes
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Command line tool for extracting StrongHelp manuals into a directory.
|
|
4
|
+
|
|
5
|
+
python -m riscos_stronghelp --extract-dir <directory> <stronghelp-file>
|
|
6
|
+
python -m riscos_stronghelp --list <stronghelp-file>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import print_function
|
|
10
|
+
import argparse
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
from riscos_stronghelp.format import StrongHelp, objtype_dir
|
|
15
|
+
|
|
16
|
+
RISCOS_FILETYPES = {
|
|
17
|
+
0xFFF: 'Text',
|
|
18
|
+
0xFFE: 'Command',
|
|
19
|
+
0xFFD: 'Data',
|
|
20
|
+
0xFFC: 'Utility',
|
|
21
|
+
0xFFB: 'BASIC',
|
|
22
|
+
0xFFA: 'Module',
|
|
23
|
+
0xFF9: 'Sprite',
|
|
24
|
+
0xFF8: 'Absolute',
|
|
25
|
+
0xFF7: 'BBC font',
|
|
26
|
+
0xFF6: 'Font',
|
|
27
|
+
0xFF5: 'PoScript',
|
|
28
|
+
0xFF4: 'Printout',
|
|
29
|
+
0xFF2: 'Config',
|
|
30
|
+
0xFF0: 'TIFF',
|
|
31
|
+
0xFD1: 'BasicTxt',
|
|
32
|
+
0xFED: 'Palette',
|
|
33
|
+
0xFEC: 'Template',
|
|
34
|
+
0xFEB: 'Obey',
|
|
35
|
+
0xFEA: 'Desktop',
|
|
36
|
+
0xFE6: 'Unix Ex',
|
|
37
|
+
0xFE5: 'EPROM',
|
|
38
|
+
0xFDC: 'SoftLink',
|
|
39
|
+
0xFD3: 'DebImage',
|
|
40
|
+
0xFCA: 'Squash',
|
|
41
|
+
0xFC9: 'SunRastr',
|
|
42
|
+
0xFAF: 'HTML',
|
|
43
|
+
0xFAE: 'Resource',
|
|
44
|
+
0xF89: 'GZip',
|
|
45
|
+
0xF81: 'JS',
|
|
46
|
+
0xF80: 'XML',
|
|
47
|
+
0xF7F: 'XML_DTD',
|
|
48
|
+
0xF7E: 'XSL',
|
|
49
|
+
0xF75: 'JSON',
|
|
50
|
+
0xF74: 'YAML',
|
|
51
|
+
0xD94: 'ArtWork',
|
|
52
|
+
0xC85: 'JPEG',
|
|
53
|
+
0xBBC: 'BBC ROM',
|
|
54
|
+
0xB61: 'XBM',
|
|
55
|
+
0xB60: 'PNG',
|
|
56
|
+
0xB2F: 'WMF',
|
|
57
|
+
0xAFF: 'DrawFile',
|
|
58
|
+
0xAAD: 'SVG',
|
|
59
|
+
0xA91: 'Zip',
|
|
60
|
+
0xA66: 'WebP',
|
|
61
|
+
0xA65: 'JPEG2000',
|
|
62
|
+
0x69E: 'PNM',
|
|
63
|
+
0x69D: 'Targa',
|
|
64
|
+
0x69C: 'BMP',
|
|
65
|
+
0x697: 'PCX',
|
|
66
|
+
0x695: 'GIF',
|
|
67
|
+
0x690: 'Clear',
|
|
68
|
+
0x1C9: 'DiagData',
|
|
69
|
+
0x132: 'ICO',
|
|
70
|
+
0x1000: 'Directory',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def extract_to_directory(sh, output_dir):
|
|
75
|
+
"""
|
|
76
|
+
Extract the whole archive to a target directory.
|
|
77
|
+
"""
|
|
78
|
+
try:
|
|
79
|
+
os.makedirs(output_dir)
|
|
80
|
+
except OSError:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
for shf in sh:
|
|
84
|
+
print("Extracting {}".format(shf.filename))
|
|
85
|
+
filename = os.path.join(output_dir, shf.unix_filename)
|
|
86
|
+
if shf.objtype == objtype_dir:
|
|
87
|
+
try:
|
|
88
|
+
os.makedirs(filename)
|
|
89
|
+
except OSError:
|
|
90
|
+
pass
|
|
91
|
+
else:
|
|
92
|
+
with open(filename, 'wb') as fh:
|
|
93
|
+
fh.write(shf.read())
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def list_files(sh):
|
|
97
|
+
"""
|
|
98
|
+
List files in the StrongHelp archive.
|
|
99
|
+
"""
|
|
100
|
+
print("{:<25} {:<12} {:>10}".format("Name", "Type", "Length"))
|
|
101
|
+
print("-" * 50)
|
|
102
|
+
for shf in sh:
|
|
103
|
+
if shf.objtype == objtype_dir:
|
|
104
|
+
type_str = "Directory"
|
|
105
|
+
elif shf.filetype == -1:
|
|
106
|
+
type_str = "None"
|
|
107
|
+
else:
|
|
108
|
+
type_str = RISCOS_FILETYPES.get(shf.filetype, "{:03x}".format(shf.filetype))
|
|
109
|
+
|
|
110
|
+
print("{:<25} {:<12} {:10d}".format(shf.filename, type_str, shf.length))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def setup_argparse():
|
|
114
|
+
parser = argparse.ArgumentParser(usage="%s [<options>] <strong-help-file>" % (os.path.basename(sys.argv[0]),))
|
|
115
|
+
parser.add_argument('file', action='store',
|
|
116
|
+
help="StrongHelp file to read")
|
|
117
|
+
parser.add_argument('--extract-dir', action='store',
|
|
118
|
+
help="Directory to extract into")
|
|
119
|
+
parser.add_argument('--list', action='store_true',
|
|
120
|
+
help="List files in the StrongHelp file")
|
|
121
|
+
|
|
122
|
+
return parser
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def main():
|
|
126
|
+
parser = setup_argparse()
|
|
127
|
+
|
|
128
|
+
options = parser.parse_args()
|
|
129
|
+
|
|
130
|
+
sh = StrongHelp(options.file)
|
|
131
|
+
|
|
132
|
+
if options.list:
|
|
133
|
+
list_files(sh)
|
|
134
|
+
elif options.extract_dir:
|
|
135
|
+
extract_to_directory(sh, options.extract_dir)
|
|
136
|
+
else:
|
|
137
|
+
# Default behavior if no action specified: list files
|
|
138
|
+
list_files(sh)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == '__main__':
|
|
142
|
+
main()
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parse the StrongHelp file format into structured data.
|
|
3
|
+
|
|
4
|
+
Example usage::
|
|
5
|
+
|
|
6
|
+
from riscos_stronghelp.format import StrongHelp, objtype_dir
|
|
7
|
+
|
|
8
|
+
sh = StrongHelp(shfilename)
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
os.makedirs(output_dir)
|
|
12
|
+
except OSError:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
for shf in sh:
|
|
16
|
+
print("{}".format(shf.filename))
|
|
17
|
+
filename = os.path.join(output_dir, shf.unix_filename)
|
|
18
|
+
if shf.objtype == objtype_dir:
|
|
19
|
+
try:
|
|
20
|
+
os.makedirs(filename)
|
|
21
|
+
except OSError:
|
|
22
|
+
pass
|
|
23
|
+
else:
|
|
24
|
+
with open(filename, 'wb') as fh:
|
|
25
|
+
fh.write(shf.read())
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import struct
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Flags in the StrongHelp file
|
|
32
|
+
flag_owner_read = (1<<0) # owner read
|
|
33
|
+
flag_owner_write = (1<<1) # owner write
|
|
34
|
+
flag_locked = (1<<3) # locked
|
|
35
|
+
flag_public_read = (1<<4) # public read
|
|
36
|
+
flag_public_write = (1<<5) # public write
|
|
37
|
+
flag_directory = (1<<8) # is directory
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# RISC OS Object types
|
|
41
|
+
objtype_file = 1
|
|
42
|
+
objtype_dir = 2
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class StrongHelpFormatError(Exception):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class StrongHelpBlock(object):
|
|
50
|
+
|
|
51
|
+
def __init__(self, sh, offset):
|
|
52
|
+
self.sh = sh
|
|
53
|
+
self.offset = offset
|
|
54
|
+
|
|
55
|
+
def read_bytes(self, size, offset=0):
|
|
56
|
+
return self.sh.read_bytes(size, self.offset + offset)
|
|
57
|
+
|
|
58
|
+
def read_word(self, offset=0):
|
|
59
|
+
return self.sh.read_word(self.offset + offset)
|
|
60
|
+
|
|
61
|
+
def read_string(self, offset=0):
|
|
62
|
+
return self.sh.read_string(self.offset + offset)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class StrongHelpObject(StrongHelpBlock):
|
|
66
|
+
|
|
67
|
+
def __init__(self, sh, offset, parent_dir, leafname, loadaddr=0, execaddr=0, flags=0, length=0):
|
|
68
|
+
super(StrongHelpObject, self).__init__(sh, offset)
|
|
69
|
+
self.parent_dir = parent_dir
|
|
70
|
+
self.leafname = leafname
|
|
71
|
+
self.loadaddr = loadaddr
|
|
72
|
+
self.execaddr = execaddr
|
|
73
|
+
self.flags = flags
|
|
74
|
+
self.length = length
|
|
75
|
+
|
|
76
|
+
#print("{} '{}' at &{:x}".format(self.__class__.__name__,
|
|
77
|
+
# self.filename, self.offset))
|
|
78
|
+
|
|
79
|
+
def __repr__(self):
|
|
80
|
+
return "<{}(name='{}', type=0x{:x}, size={})>".format(self.__class__.__name__,
|
|
81
|
+
self.filename,
|
|
82
|
+
self.filetype,
|
|
83
|
+
self.length)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def attributes(self):
|
|
87
|
+
"""
|
|
88
|
+
RISC OS File attributes.
|
|
89
|
+
"""
|
|
90
|
+
# Just the bottom 8 bits
|
|
91
|
+
return self.flags & 0xFF
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def objtype(self):
|
|
95
|
+
"""
|
|
96
|
+
RISC OS object type.
|
|
97
|
+
"""
|
|
98
|
+
return objtype_dir if (self.flags & flag_directory) else objtype_file
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def filetype(self):
|
|
102
|
+
if self.flags & flag_directory:
|
|
103
|
+
return 0x1000
|
|
104
|
+
if self.loadaddr & 0xFFF00000 == 0xFFF00000:
|
|
105
|
+
return (self.loadaddr >> 8) & 0xFFF
|
|
106
|
+
return -1
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def filename(self):
|
|
110
|
+
if not self.parent_dir:
|
|
111
|
+
return self.leafname
|
|
112
|
+
parent = self.parent_dir.filename
|
|
113
|
+
return "{}.{}".format(parent, self.leafname)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def unix_filename(self):
|
|
117
|
+
leafname = self.leafname.replace('/', '.')
|
|
118
|
+
if not self.parent_dir:
|
|
119
|
+
return leafname
|
|
120
|
+
|
|
121
|
+
if self.filetype in (0xFFF, 0x1000):
|
|
122
|
+
# A text file or a directory
|
|
123
|
+
suffix = ''
|
|
124
|
+
|
|
125
|
+
elif self.filetype == -1:
|
|
126
|
+
# Not filetyped - there's a load and exec address.
|
|
127
|
+
# We will treat these as Data for now - the strongcopy tool
|
|
128
|
+
# doesn't support load and exec formats.
|
|
129
|
+
suffix = ',ffd'
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
# Other filetypes
|
|
133
|
+
suffix = ',%03x' % (self.filetype,)
|
|
134
|
+
|
|
135
|
+
parent = self.parent_dir.unix_filename
|
|
136
|
+
if parent == '$':
|
|
137
|
+
return leafname + suffix
|
|
138
|
+
else:
|
|
139
|
+
return "{}/{}{}".format(parent, leafname, suffix)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class StrongHelpFile(StrongHelpObject):
|
|
143
|
+
|
|
144
|
+
def __init__(self, sh, offset, parent_dir, leafname, loadaddr=0, execaddr=0, flags=0, length=0):
|
|
145
|
+
super(StrongHelpFile, self).__init__(sh, offset, parent_dir, leafname, loadaddr, execaddr, flags, length)
|
|
146
|
+
|
|
147
|
+
if offset == 0:
|
|
148
|
+
# This is a 0 byte file
|
|
149
|
+
self.size = 0
|
|
150
|
+
|
|
151
|
+
else:
|
|
152
|
+
if self.read_bytes(4, offset=0) != b'DATA':
|
|
153
|
+
raise StrongHelpFormatError("Bad file entry '{}' at offset &{:x}: "
|
|
154
|
+
"Block header is invalid".format(self.filename,
|
|
155
|
+
offset))
|
|
156
|
+
|
|
157
|
+
self.size = self.read_word(4)
|
|
158
|
+
if self.size < self.length:
|
|
159
|
+
raise StrongHelpFormatError("Bad file entry '{}' at offset &{:x}: "
|
|
160
|
+
"Block is too small ({}) for file length ({})".format(self.filename,
|
|
161
|
+
offset,
|
|
162
|
+
self.size,
|
|
163
|
+
self.length))
|
|
164
|
+
|
|
165
|
+
def read(self, encoding=None):
|
|
166
|
+
if not self.size:
|
|
167
|
+
data = b''
|
|
168
|
+
else:
|
|
169
|
+
data = self.read_bytes(self.length - 8, offset=8)
|
|
170
|
+
if encoding:
|
|
171
|
+
data = data.decode(encoding)
|
|
172
|
+
|
|
173
|
+
return data
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class StrongHelpDir(StrongHelpObject):
|
|
177
|
+
|
|
178
|
+
def __init__(self, sh, offset, parent_dir, leafname, loadaddr=0, execaddr=0, flags=0, length=0):
|
|
179
|
+
super(StrongHelpDir, self).__init__(sh, offset, parent_dir, leafname, loadaddr, execaddr, flags, length)
|
|
180
|
+
|
|
181
|
+
if self.read_bytes(4, offset=0) != b'DIR$':
|
|
182
|
+
raise StrongHelpFormatError("Bad directory entry '{}' at offset &{:x}: "
|
|
183
|
+
"Block header is invalid".format(self.filename,
|
|
184
|
+
offset))
|
|
185
|
+
|
|
186
|
+
self.dir_size = self.read_word(4)
|
|
187
|
+
self.dir_used = self.read_word(8)
|
|
188
|
+
|
|
189
|
+
if self.dir_used > self.dir_size:
|
|
190
|
+
raise StrongHelpFormatError("Bad directory entry '{}' at offset &{:x}: "
|
|
191
|
+
"Block is too small ({}) for used size ({})".format(self.filename,
|
|
192
|
+
offset,
|
|
193
|
+
self.dir_size,
|
|
194
|
+
self.dir_used))
|
|
195
|
+
if self.dir_used < 12 + 24:
|
|
196
|
+
raise StrongHelpFormatError("Bad directory entry '{}' at offset &{:x}: "
|
|
197
|
+
"Block is too small ({}) for directory entry".format(self.filename,
|
|
198
|
+
offset,
|
|
199
|
+
self.dir_used))
|
|
200
|
+
|
|
201
|
+
self.objects = []
|
|
202
|
+
offset = 12
|
|
203
|
+
while offset < self.dir_used:
|
|
204
|
+
#print("--- file in dir {}, offset &{:x} ---".format(self.filename, offset))
|
|
205
|
+
object_offset = self.read_word(offset + 0)
|
|
206
|
+
loadaddr = self.read_word(offset + 4)
|
|
207
|
+
execaddr = self.read_word(offset + 8)
|
|
208
|
+
length = self.read_word(offset + 12)
|
|
209
|
+
flags = self.read_word(offset + 16)
|
|
210
|
+
reserved = self.read_word(offset + 20)
|
|
211
|
+
# FIXME: Assuming the filename encoding is latin-1 (probably correct, but not configurable)
|
|
212
|
+
name_bytes = self.read_string(offset + 24)
|
|
213
|
+
name = name_bytes.decode('latin-1')
|
|
214
|
+
offset += 24 + (len(name_bytes) + 4) & ~3
|
|
215
|
+
|
|
216
|
+
if flags & flag_directory:
|
|
217
|
+
shfile = StrongHelpDir(self.sh, object_offset, parent_dir=self, leafname=name,
|
|
218
|
+
loadaddr=loadaddr, execaddr=execaddr, flags=flags, length=length)
|
|
219
|
+
else:
|
|
220
|
+
shfile = StrongHelpFile(self.sh, object_offset, parent_dir=self, leafname=name,
|
|
221
|
+
loadaddr=loadaddr, execaddr=execaddr, flags=flags, length=length)
|
|
222
|
+
self.objects.append(shfile)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class StrongHelp(object):
|
|
226
|
+
|
|
227
|
+
def __init__(self, filename=None, data=None):
|
|
228
|
+
self.filename = filename
|
|
229
|
+
if data:
|
|
230
|
+
self.data = data
|
|
231
|
+
else:
|
|
232
|
+
with open(filename, 'rb') as fh:
|
|
233
|
+
self.data = fh.read()
|
|
234
|
+
|
|
235
|
+
if self.data[0:4] != b'HELP':
|
|
236
|
+
raise StrongHelpFormatError("This is not a StrongHelp file")
|
|
237
|
+
|
|
238
|
+
self.root_size = self.read_word(4)
|
|
239
|
+
self.stronghelp_version = self.read_word(8)
|
|
240
|
+
self.free_list = self.read_word(12)
|
|
241
|
+
|
|
242
|
+
self.root_offset = self.read_word(16)
|
|
243
|
+
|
|
244
|
+
#print("Root offset = %08x" % (self.root_offset,))
|
|
245
|
+
|
|
246
|
+
self.root = StrongHelpDir(self, self.root_offset, parent_dir=None, leafname='$')
|
|
247
|
+
|
|
248
|
+
def __iter__(self):
|
|
249
|
+
"""
|
|
250
|
+
List all the files in the StrongHelp file.
|
|
251
|
+
"""
|
|
252
|
+
shdirs = [self.root]
|
|
253
|
+
while shdirs:
|
|
254
|
+
shdir = shdirs.pop()
|
|
255
|
+
for shobj in shdir.objects:
|
|
256
|
+
if isinstance(shobj, StrongHelpDir):
|
|
257
|
+
shdirs.append(shobj)
|
|
258
|
+
yield shobj
|
|
259
|
+
|
|
260
|
+
def read_word(self, offset):
|
|
261
|
+
#print("Read word at &{:x}".format(offset))
|
|
262
|
+
(data,) = struct.unpack('<L', self.data[offset:offset + 4])
|
|
263
|
+
#print(" &{:08x} = {}".format(data, data))
|
|
264
|
+
return data
|
|
265
|
+
|
|
266
|
+
def read_bytes(self, size, offset):
|
|
267
|
+
return self.data[offset:offset + size]
|
|
268
|
+
|
|
269
|
+
def read_string(self, offset):
|
|
270
|
+
start = offset
|
|
271
|
+
while offset < len(self.data) and self.data[offset:offset+1] != b'\0':
|
|
272
|
+
offset += 1
|
|
273
|
+
return self.data[start:offset]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: riscos-stronghelp
|
|
3
|
+
Version: 0.3.16
|
|
4
|
+
Summary: Extract RISC OS StrongHelp manuals
|
|
5
|
+
Home-page: https://github.com/gerph/riscos-stronghelp-python
|
|
6
|
+
Author: Charles Ferguson
|
|
7
|
+
Author-email: gerph@gerph.org
|
|
8
|
+
License: MIT
|
|
9
|
+
Description: # Python StrongHelp reader
|
|
10
|
+
|
|
11
|
+
This repository contains a reader for the RISC OS StrongHelp manual image format.
|
|
12
|
+
|
|
13
|
+
The Python module is able to be used to parse the format and return the files
|
|
14
|
+
which are present. The module can also be used as a command line tool to
|
|
15
|
+
extract the files to a unix file system.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
The tool for extracting StrongHelp files can be installed manually
|
|
21
|
+
using this repository or through PyPI. To install, use:
|
|
22
|
+
|
|
23
|
+
pip3 install riscos_stronghelp
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Command line
|
|
27
|
+
|
|
28
|
+
At the command line the extraction tool may be used with the
|
|
29
|
+
supplied shell command:
|
|
30
|
+
|
|
31
|
+
riscos-shextract [--extract-dir <directory>] <stronghelp-file>
|
|
32
|
+
|
|
33
|
+
Or to list files:
|
|
34
|
+
|
|
35
|
+
riscos-shextract --list <stronghelp-file>
|
|
36
|
+
|
|
37
|
+
Keywords: riscos
|
|
38
|
+
Platform: UNKNOWN
|
|
39
|
+
Classifier: Development Status :: 4 - Beta
|
|
40
|
+
Classifier: Intended Audience :: Developers
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Programming Language :: Python :: 2.7
|
|
43
|
+
Classifier: Programming Language :: Python :: 3
|
|
44
|
+
Classifier: Operating System :: OS Independent
|
|
45
|
+
Requires-Python: >=2.7
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
riscos_stronghelp/__init__.py
|
|
4
|
+
riscos_stronghelp/__main__.py
|
|
5
|
+
riscos_stronghelp/format.py
|
|
6
|
+
riscos_stronghelp.egg-info/PKG-INFO
|
|
7
|
+
riscos_stronghelp.egg-info/SOURCES.txt
|
|
8
|
+
riscos_stronghelp.egg-info/dependency_links.txt
|
|
9
|
+
riscos_stronghelp.egg-info/entry_points.txt
|
|
10
|
+
riscos_stronghelp.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
riscos_stronghelp
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Packaging for the riscos_stronghelp package.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from distutils.core import setup
|
|
7
|
+
import setuptools # noqa
|
|
8
|
+
|
|
9
|
+
from os import path
|
|
10
|
+
# io.open is needed for projects that support Python 2.7
|
|
11
|
+
# It ensures open() defaults to text mode with universal newlines,
|
|
12
|
+
# and accepts an argument to specify the text encoding
|
|
13
|
+
# Python 3 only projects can skip this import
|
|
14
|
+
from io import open
|
|
15
|
+
|
|
16
|
+
here = path.abspath(path.dirname(__file__))
|
|
17
|
+
|
|
18
|
+
# Get the long description from the README file
|
|
19
|
+
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
|
|
20
|
+
long_description = f.read()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
setup(
|
|
24
|
+
name = 'riscos_stronghelp',
|
|
25
|
+
packages = ['riscos_stronghelp'],
|
|
26
|
+
version = "0.3.16",
|
|
27
|
+
license='MIT',
|
|
28
|
+
description = 'Extract RISC OS StrongHelp manuals',
|
|
29
|
+
long_description = long_description,
|
|
30
|
+
long_description_content_type = 'text/markdown',
|
|
31
|
+
author = 'Charles Ferguson',
|
|
32
|
+
author_email = 'gerph@gerph.org',
|
|
33
|
+
url = 'https://github.com/gerph/riscos-stronghelp-python',
|
|
34
|
+
keywords = ['riscos'],
|
|
35
|
+
entry_points={ 'console_scripts': ['riscos-shextract = riscos_stronghelp.__main__:main'] },
|
|
36
|
+
install_requires= [
|
|
37
|
+
],
|
|
38
|
+
classifiers= [
|
|
39
|
+
'Development Status :: 4 - Beta',
|
|
40
|
+
'Intended Audience :: Developers',
|
|
41
|
+
'License :: OSI Approved :: MIT License',
|
|
42
|
+
'Programming Language :: Python :: 2.7',
|
|
43
|
+
'Programming Language :: Python :: 3',
|
|
44
|
+
"Operating System :: OS Independent",
|
|
45
|
+
],
|
|
46
|
+
python_requires='>=2.7',
|
|
47
|
+
)
|