-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhexe.kex
174 lines (159 loc) · 9.28 KB
/
hexe.kex
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
'set novalue on' /* force KEXX and its way of SIGNAL ON NOVALUE */
/* Usage: [MACRO] HEXE [file [ ( init-options [)] ]] */
/* Or: KEDIT file (PROFile HEXE [init-options[)]] */
/* Example: HEXE kedit.exe => Kedit binary KEDIT.EXE */
/* HEXE => hex. view current file */
/* Purpose: (Ab)use KEDIT as hex. editor. If HEXE is used */
/* within Kedit it "copies" some local file + view */
/* settings like colours, ARROW, ARBCHAR, or WRAP. */
/* Otherwise HEXE tries to DEFINE INITIAL.KML and */
/* tries to execute MACRO COLOR / MONO / WINDOWS. */
/* INITIAL.KML and COLOR.KEX are only used to get */
/* "normal" file + view settings like colours etc. */
/* Update 2008: HEXE uses the current window width. An optimal */
/* width is 100 or 106 columns. Ask QUERY LSCREEN */
/* for the window width, it is the third value for */
/* Kedit 5.0 and the last value for KeditW 1.0. */
/* For 76 up to 99 columns HEXE.KEX still shows 24 */
/* hex. bytes per line. If you need to calculate */
/* hex. offsets 16 bytes are better, use HEXA.KEX */
/* for this purpose, HEXA is otherwise identical. */
/* See also: Macro A-F12 in INITIAL.KML toggles normal and */
/* binary views. Normal view would also reset all */
/* binary settings to normal defprof.1() values. */
/* If macro ZOO.KEX is assigned to a key 'zoo .' */
/* reports the binary offset of the focus column. */
/* For the "reload strategy" used by HEXE.KEX see */
/* also BINARY, BROWSE, HEXA, or UNIX.KEX. This */
/* macro automatically uses PROFDEBUG if "DEFINEd" */
/* by TRACE.KEX for debugging. */
/* Position: The actual position in the file is preserved if */
/* possible. This fails if an intended EOLOUT LF */
/* or CRLF does not reflect the actually used EOL */
/* character(s) for files not yet saved with this */
/* intended EOLOUT. The EOLIN value does not help */
/* in this scenario, EOLIN LF in essence means LF */
/* or CRLF. File positions depending on EOFIN and */
/* EOFOUT also cannot be accurately preserved, but */
/* affect only the last line or record. Likewise */
/* TABSIN, TABSOUT, or TRAILING can confuse binary */
/* offsets. Function length.1() correctly counts */
/* trailing blanks only for TRAILING ON. */
/* Caveats: Do not use Kedit to insert or delete bytes in a */
/* binary. It is possible to replace bytes in a */
/* binary loaded by HEXE if some critical settings */
/* are not changed: EOFOUT, EOLOUT, LRECL, RECFM, */
/* TABSOUT, TRAILING. Please check the file size */
/* of a patched binary, it should be the same. */
/* Optional: INITIAL.KML, COLOR.KEX, MONO.KEX, WINDOWS.KEX, */
/* STATUS.KEX (to report Kedit 5 TRUNC workaround) */
/* Requires: Kedit 5.0 or KeditW 1.0 (Frank Ellermann, 2008) */
if profile() then exit EDIT() ; else PROF = INIT()
if arg( 1 ) <> '' then do /* accept one file + options: */
Q = left( strip( arg( 1 )), 1 )
if Q = '"' | Q = "'" then parse arg (Q) FILE (Q) Q '(' R
else parse arg FILE Q '(' R
parse var R OPTS ')' R ; R = length( strip( Q R ))
if R + pos( 'PROF', translate( OPTS )) > 0 then do
'emsg HEXE' arg( 1 ) '?!?' ; exit 20
end /* avoid PROF-option conflict */
'kedit "' || strip( FILE ) || '" (PROFile' PROF OPTS || ')'
if undo.3() + size.1() + alt() + rc = 0 then do
FILE = fileid.1() ; 'quit'
'emsg HEXE found no' FILE ; exit 28
end /* empty binary is a bad plan */
exit rc /* anything else done as PROF */
end /* -------------------------- */
'extract /FEXT/FILEID'
if dir() | alt() then do /* cannot reload changed file */
'emsg save' FILEID.1 'first, HEXE has to reload this file'
'cmsg save' ; exit 12
end
if FEXT.1 = 'BAK' then 'fext TMP' ; else 'fext BAK'
if rc <> 0 then exit rc ; FILEID.0 = fileid.1()
Q = eolout.1() <> 'NONE' /* text EOL at length.1() + 1 */
Q = max( 0, -1 + min( column.1(), Q + length.1()))
R = max( 0, -1 + min( line.1(), size.1()))
if eolout.1() <> 'NONE' then do /** EOLOUT CR 1, LF 1, CRLF 2 */
Q = Q + R * ( 2 - ( 'CRLF' <> eolout.1()))
if tabsout.1() = 'ON' then do
'compress -*' ; 'locate :' R + 1
end /* length.1() includes blanks */
do until rc <> 0 /* for TRAILING ON, 0 for TOF */
'up' ; Q = Q + length.1()
end /* undo TABSO, edit can fail: */
if tabsout.1() = 'ON' then do until 1
'undo' ; if rc = 0 then leave
'expand' R + 2 ; 'set alt 0 0'
end /* position in actual line is */
end /* not accurate if COMPRESSed */
else Q = Q + R * lrecl.1() /* determines a binary offset */
'kedit "' || FILEID.1 || '" (PROFile' PROF || ')'
if rc <> 0 then do /* trouble: reset old fileid */
R = rc ; 'fext' FEXT.2 ; exit R
end
'kedit "' || FILEID.0 || '" (NEW)' ; 'quit'
'kedit "' || FILEID.1 || '" (NEW)' ; R = lrecl.1()
'locate :' || ( 1 + Q % R ) 'clocate :' ( 1 + Q // R )
exit 0
EDIT: procedure /* -------------------------------------------- */
if initial() then do /* initialize global settings */
'nomsg define initial.kml' ; 'nomsg macro' monitor.1()
end
if version.1() = 'KEDIT' then 'scr 1'
else 'win max'
'nomsg editv get HEXE.0'
if HEXE.0 = '' then do /* save local settings HEXE.n */
'reprof on' ; 'wrap on' ; 'arrow off'
'shifts on' ; 'arbchar on' ; 'backup temp'
'number on' ; 'hexdisp on' ; 'varblank on'
call INIT ; 'editv get HEXE.0'
end
do N = 1 to HEXE.0 /* load local settings HEXE.n */
'editv get HEXE.' || N ; 'set' HEXE.N
end /* -------------------------------------------- */
COL = 4 /* should be 8, 16, or 32, but VER accepts only */
/* 20 arg.s, so COL * 4 + 4 <= 20 is the limit. */
if lscreen.2() < 16 * 3 + COL then LEN = 8 /* 40 ? */
else if lscreen.2() < 24 * 3 + COL then LEN = 16 /* oops! */
else if lscreen.2() < 32 * 3 + COL then LEN = 24 /* 80 ? */
else LEN = 32 /* 132 ? */
if LEN * 3 + COL + 6 <= lscreen.2() then 'prefix on right'
if version.1() <> 'KEDIT' then 'boundmark verify zone'
'hex on' ; 'beep on' ; 'autoscroll off'
'trailing on' ; 'recfm vary' /** use 11 critical settings **/
'lrecl' LEN ; 'trunc' LEN ; 'zone 1' LEN
'eofin allow' ; 'eolin none' ; 'tabsin off'
'eofout none' ; 'eolout none' ; 'tabsout off'
/* RECFM FIXED would add blanks to the last line up to LRECL, */
/* for patching binaries this is no good idea. Use HEXE only */
/* for viewing and maybe replacing some bytes. CAVEAT: Do not */
/* insert or delete bytes or "lines" (= records = LEN bytes). */
SPACE = 2 * LEN ; R = '' ; S = R ; V = R
do J = 1 to LEN by LEN % COL /* process record, COL parts */
K = LEN % COL + J - 1
do I = J - 1 to K - 1 /* process a part of record: */
R = R d2x( I // 16 ) /* build text for RESERVED */
S = S || d2x( I // 16 )
end
R = R '' /* build text for the VERIFY */
V = V 'H' || J K SPACE SPACE
end /* Hex. col.s J to K, + space */
'reserved' msgline.2() attr.11() R || S
'set verify' V 1 LEN SPACE '*' ; if rc <> 0 then exit rc
'nomsg locate :1' /* avoid 5.0 SL1+2 TRUNC bug: */
if LEN = 1 + length.1() then 'trunc' LEN + 1
'nomsg locate :0 macro status' /* restore TOP, check STATUS */
if 0 <= rc then 'macro status' ; return 0
INIT: procedure /* -------------------------------------------- */
SET = 'attr arbchar arrow backup number undoing varblank wrap'
if version.1() <> 'KEDIT' then do
if toolset.2() = 'USER' then SET = SET 'toolset'
end
HEXE.0 = words( SET ) ; 'editv put HEXE.0'
do N = 1 to HEXE.0
'nomsg query' word( SET, N ) ; HEXE.N = lastmsg.1()
'editv put HEXE.' || N
end
parse source . . PROF ; 'nomsg query macro' PROF
if rc <> 0 then return PROF ; return PROF 'PROFDEBUG'