final clean up
[sped.git] / repl.asm
1 ; sped - the stupidly pointless editor
2 ; written by pinosaur
3 ; repl.asm: user interactions
4
5 extern printf
6 extern fflush
7 extern stdout
8 extern free
9
10 extern readLine
11 extern writeFile
12 extern shiftLeft
13 extern shiftRight
14
15 global repl
16
17 section .data
18     prompt_str db `sped > `, 0x00
19     invalidcmd_str db `invalid command.\n`, 0x00
20     invalidaddr_str db `invalid address.\n`, 0x00
21     oneline_str db `cannot delete line, as there is only one line.\n`, 0x00
22     currentline_str db `current line: %i\n`, 0x00
23     echo_str db `%s`, 0x00 ; print strings without format exploit
24
25 section .bss
26     buffer resb 4
27     buffer_lines resb 4
28     buffer_filename resb 4
29     cur_line resb 4
30
31 section .text
32
33 ; prompt for user
34 ; args: buffer, buffer_lines, buffer_filename
35 repl:
36
37     %define _BUFFER          16
38     %define _BUFFER_LINES    12
39     %define _BUFFER_FILENAME 8
40     %define CMDSTR           4 ; the previous line read from user
41
42     push ebp
43     mov ebp, esp
44
45     sub esp, 4
46     
47     ; set bss vars
48     mov eax, [ebp+_BUFFER]
49     mov [buffer], eax
50     mov eax, [ebp+_BUFFER_LINES]
51     mov [buffer_lines], eax
52     mov eax, [ebp+_BUFFER_FILENAME]
53     mov [buffer_filename], eax
54     mov DWORD [cur_line], 0x00
55
56     _repl_loop:
57     
58     ; print the prompt
59     push prompt_str
60     call printf
61     push DWORD [stdout]
62     call fflush
63
64     ; read line from stdin
65     push 0
66     call readLine
67
68     mov DWORD [ebp-CMDSTR], eax
69
70     ; commands are single char for now
71     cmp ecx, 1 
72     jne _repl_invalid_cmd
73
74     ; parse commands
75     mov eax, DWORD [ebp-CMDSTR]
76     mov eax, [eax]
77
78     ; q exists program =-=-=-=-=-=-=-=-=-=-=-=-=
79     mov eax, DWORD [ebp-CMDSTR]
80     cmp BYTE [eax], 'q'
81     jne _repl_cmd_quit_end
82     jmp _repl_exit
83     _repl_cmd_quit_end:
84
85     ; p prints current line =-=-=-=-=-=-=-=-=-=-=
86     mov eax, DWORD [ebp-CMDSTR]
87     cmp BYTE [eax], 'p'
88     jne _repl_cmd_print_end
89
90     mov eax, DWORD [cur_line]
91     mov ecx, 4
92     mul ecx
93     add eax, [buffer]
94     push DWORD [eax]
95     push echo_str
96     call printf
97     jmp _repl_continue
98     _repl_cmd_print_end:
99
100     ; n prints the current line number =-=-=-=-=-=-=-=
101     mov eax, DWORD [ebp-CMDSTR]
102     cmp BYTE [eax], 'n'
103     jne _repl_cmd_number_end
104
105     push DWORD [cur_line]
106     push currentline_str
107     call printf
108
109     jmp _repl_continue
110     _repl_cmd_number_end:
111
112     ; - goes to prev line =-=-=-=-=-=-=-=-=-=-=-=-=
113     mov eax, DWORD [ebp-CMDSTR]
114     cmp BYTE [eax], '-'
115     jne _repl_cmd_decline_end
116
117     ; make sure we are within bounds
118     mov eax, DWORD [cur_line] 
119     sub eax, 1
120     cmp eax, 0
121     jl _repl_invalid_addr
122     
123     sub DWORD [cur_line], 1
124
125     jmp _repl_continue
126     _repl_cmd_decline_end:
127
128     ; + goes to next line =-=-=-=-=-=-=-=-=-=-=-=-=
129     mov eax, DWORD [ebp-CMDSTR]
130     cmp BYTE [eax], '+'
131     jne _repl_cmd_incline_end
132
133     ; make sure we are within bounds 
134     mov eax, DWORD [cur_line] 
135     add eax, 1
136     cmp eax, [buffer_lines]
137     jge _repl_invalid_addr
138     
139     add DWORD [cur_line], 1
140
141     jmp _repl_continue
142     _repl_cmd_incline_end:
143
144     ; g goes to first line =-=-=-=-=-=-=-=-=-=-=-=-=
145     mov eax, DWORD [ebp-CMDSTR]
146     cmp BYTE [eax], 'g'
147     jne _repl_cmd_jumptop_end
148
149     mov DWORD [cur_line], 0x00
150
151     jmp _repl_continue
152     _repl_cmd_jumptop_end:
153
154     ; G goes to last line =-=-=-=-=-=-=-=-=-=-=-=-=
155     mov eax, DWORD [ebp-CMDSTR]
156     cmp BYTE [eax], 'G'
157     jne _repl_cmd_jumpbot_end
158
159     mov eax, DWORD [buffer_lines]
160     sub eax, 1
161     mov DWORD [cur_line], eax
162
163     jmp _repl_continue
164     _repl_cmd_jumpbot_end:
165
166     ; c changes the current line =-=-=-=-=-=-=-=-=-=
167     mov eax, DWORD [ebp-CMDSTR]
168     cmp BYTE [eax], 'c'
169     jne _repl_cmd_change_end
170
171     ; read a new line to use
172     push 0
173     call readLine
174
175     mov esi, eax
176
177     ; free old string
178     mov eax, [cur_line]
179     mov ecx, 4
180     mul ecx
181     add eax, [buffer]
182     push DWORD [eax]
183     call free
184
185     ; insert new string
186     mov eax, [cur_line]
187     mov ecx, 4
188     mul ecx
189     add eax, DWORD [buffer]
190     mov [eax], esi
191
192     jmp _repl_continue
193     _repl_cmd_change_end:
194
195     ; d delete line =-=-=-=-=-=-=-=-=-=-=-=-=
196     mov eax, DWORD [ebp-CMDSTR]
197     cmp BYTE [eax], 'd'
198     jne _repl_cmd_delete_end
199     
200     ; check to make sure we don't have only one line
201     cmp DWORD [buffer_lines], 1
202     jle _repl_oneline
203
204     ; delete the line
205     push DWORD [buffer]
206     push DWORD [buffer_lines]
207     push DWORD [cur_line]
208     call shiftLeft
209     mov [buffer], eax
210
211     sub DWORD [buffer_lines], 1
212
213     ; if it's the last line, move one down
214     mov eax, DWORD [buffer_lines]
215     cmp DWORD [cur_line], eax
216     jl _repl_continue
217     sub DWORD [cur_line], 1
218
219     jmp _repl_continue
220     _repl_cmd_delete_end:
221
222     ; o appends text after line =-=-=-=-=-=-=-=-=
223     mov eax, DWORD [ebp-CMDSTR]
224     cmp BYTE [eax], 'o'
225     jne _repl_cmd_appenddown_end
226
227     ; make room first
228     push DWORD [buffer]
229     push DWORD [buffer_lines]
230     mov eax, DWORD [cur_line]
231     add eax, 1
232     push eax
233     call shiftRight
234     mov [buffer], eax
235
236     ; input text
237     push 0
238     call readLine
239     mov esi, eax
240
241     ; insert new string
242     mov eax, [cur_line]
243     add eax, 1
244     mov ecx, 4
245     mul ecx
246     add eax, DWORD [buffer]
247     mov [eax], esi
248
249     add DWORD [buffer_lines], 1
250
251     jmp _repl_continue
252     _repl_cmd_appenddown_end:
253
254     ; O oppens text before line =-=-=-=-=-=-=-=
255     mov eax, DWORD [ebp-CMDSTR]
256     cmp BYTE [eax], 'O'
257     jne _repl_cmd_appendup_end
258
259     ; make room first
260     push DWORD [buffer]
261     push DWORD [buffer_lines]
262     push DWORD [cur_line]
263     call shiftRight
264     mov [buffer], eax
265
266     ; input text
267     push 0
268     call readLine
269     mov esi, eax
270
271     ; insert new string
272     mov eax, [cur_line]
273     mov ecx, 4
274     mul ecx
275     add eax, DWORD [buffer]
276     mov [eax], esi
277     
278     ; also move cursor down one
279     add DWORD [cur_line], 1
280
281     add DWORD [buffer_lines], 1
282
283     jmp _repl_continue
284     _repl_cmd_appendup_end:
285
286
287     ; w writes file =-=-=-=-=-=-=-=-=-=-=-=-=
288     mov eax, DWORD [ebp-CMDSTR]
289     cmp BYTE [eax], 'w'
290     jne _repl_cmd_write_end
291
292     push DWORD [buffer_filename]
293     push DWORD [buffer]
294     push DWORD [buffer_lines]
295     call writeFile
296
297     jmp _repl_continue
298     _repl_cmd_write_end:
299
300
301     ; if no commands were matched, it's an error
302     jmp _repl_invalid_cmd
303
304     ; some error messages
305     _repl_invalid_cmd:
306     push invalidcmd_str
307     call printf
308     jmp _repl_continue
309
310     _repl_invalid_addr:
311     push invalidaddr_str
312     call printf
313     jmp _repl_continue
314
315     _repl_oneline:
316     push oneline_str
317     call printf
318     jmp _repl_continue
319
320     _repl_continue:
321     jmp _repl_loop
322     
323     _repl_exit:
324
325     %undef _BUFFER
326     %undef _BUFFER_LINES
327     %undef _BUFFER_FILENAME
328     %undef CMDSTR
329
330     mov esp, ebp
331     pop ebp
332     ret
333