Browse Source

Implemented argument completion

Yann Weber 1 year ago
parent
commit
6e5c08b2ff
3 changed files with 180 additions and 19 deletions
  1. 2
    0
      asmsh.c
  2. 151
    8
      completion.c
  3. 27
    11
      completion.h

+ 2
- 0
asmsh.c View File

@@ -86,6 +86,8 @@ int main(int argc, char *argv[], char *envp[])
86 86
 		perror("Unable to init compilation ctx");
87 87
 	}
88 88
 
89
+	rl_special_prefixes="";
90
+	rl_basic_word_break_characters=" \t\n";
89 91
 	rl_attempted_completion_function =  asmsh_rl_completion;
90 92
 
91 93
 	status = 0;

+ 151
- 8
completion.c View File

@@ -1,7 +1,5 @@
1 1
 #include "completion.h"
2 2
 
3
-/// Replace uppper char leading macro if needed
4
-static int _completion_upper_macro(const char *macro, const char *start, char **ret, size_t *i);
5 3
 
6 4
 char **asmsh_completion(const char *buf, const char *text, int start, int end)
7 5
 {
@@ -22,6 +20,8 @@ char **asmsh_completion(const char *buf, const char *text, int start, int end)
22 20
 }
23 21
 
24 22
 
23
+/// Replace uppper char leading macro if needed
24
+static int _completion_upper_macro(const char *macro, const char *start, char **ret, size_t *i);
25 25
 char **asmsh_compl_instr(const char *start)
26 26
 {
27 27
 	const size_t icount = sizeof(x86_64_instr)/sizeof(*x86_64_instr);
@@ -116,23 +116,46 @@ err_strdup:
116 116
 
117 117
 
118 118
 
119
+/// match against macro
120
+static int _completion_macro_match(const char *macro, const char *buf, int mlen);
119 121
 char **asmsh_compl_arg(const char *buf, const char *text, int start)
120 122
 {
121
-	char **ret;
123
+	const asmsh_compinstr_t *match = NULL;
124
+	int argno;
125
+	int i, tlen;
126
+	int matchlen = 0;
127
+	int macro = 0;
128
+
129
+	char **ret = malloc(sizeof(char*)*512); /* large enough */
130
+	if(!ret)
131
+	{
132
+		perror("unable to allocate buffer");
133
+		return NULL;
134
+	}
135
+	bzero(ret, sizeof(char*)*512);
122 136
 
123
-	int match = -1;
137
+	tlen = text?strlen(text):0;
124 138
 
125 139
 	for(int i=0; i<(sizeof(x86_64_instr)/sizeof(*x86_64_instr))-1; i++)
126 140
 	{
141
+		int cmp;
127 142
 		const char *instr = x86_64_instr[i].mnemo;
128 143
 		int ilen = strlen(instr);
129
-		int macro = 0;
144
+		macro=0;
130 145
 		if(instr[ilen-1] >= 'A' && instr[ilen-1] <= 'Z')
131 146
 		{
132 147
 			ilen--;
133 148
 			macro = 1;
149
+			cmp = _completion_macro_match(instr, buf, ilen);
150
+			if(cmp < 0)
151
+			{
152
+				goto err;
153
+			}
154
+		}
155
+		else
156
+		{
157
+			cmp = strncmp(buf, instr, ilen);
134 158
 		}
135
-		int cmp = strncmp(buf, instr, ilen);
136 159
 		if(cmp < 0)
137 160
 		{
138 161
 			break;
@@ -146,17 +169,102 @@ char **asmsh_compl_arg(const char *buf, const char *text, int start)
146 169
 			continue; //not a full match
147 170
 		}
148 171
 		// match or approximate macro match
149
-		match = i;
172
+		match = &x86_64_instr[i];
173
+		matchlen = ilen;
174
+		while(buf[matchlen] && buf[matchlen] != ' ' && buf[matchlen] != '\t')
175
+		{
176
+			matchlen++;
177
+		}
150 178
 		break;
151 179
 	}
152
-	if(match < 0)
180
+	if(!match)
153 181
 	{
154 182
 		ret = malloc(sizeof(char*));
155 183
 		*ret = NULL;
156 184
 		return ret;
157 185
 	}
186
+	argno=0;
187
+	for(i=matchlen; i<=start; i++)
188
+	{
189
+		if(buf[i] == ',')
190
+		{
191
+			argno=1;
192
+		}
193
+	}
194
+
195
+	int args = argno?match->arg2:match->arg1;
196
+	if(macro && match->mnemo[strlen(match->mnemo)-1] == 'S')
197
+	{
198
+		int wreg=ASHCOMP_REGALL;
199
+		switch(buf[matchlen-1])
200
+		{
201
+			case 'b'://M_sizes[0]:
202
+				wreg = ASHCOMP_REG8;
203
+				break;
204
+			case 'w'://M_sizes[1]:
205
+				wreg = ASHCOMP_REG16;
206
+				break;
207
+			case 'd'://M_sizes[2]:
208
+				wreg = ASHCOMP_REG32;
209
+				break;
210
+			case 'q'://M_sizes[3]:
211
+				wreg = ASHCOMP_REG64;
212
+				break;
213
+			default:
214
+				wreg = ASHCOMP_REGALL;
215
+				break;
216
+		}
217
+		args &= (0xff ^ ASHCOMP_REGALL) | wreg;
218
+	}
219
+
220
+	i=0;// result index
221
+	for(const asmsh_symtable_elt_t *elt=asmsh_symtable; elt->regs; elt++)
222
+	{
223
+		if(!(elt->flag & args))
224
+		{
225
+			continue;
226
+		}
227
+		if(elt->flag == ASHCOMP_IMM && tlen > 1 && *text=='$')
228
+		{
229
+			// immediate value handling
230
+			continue;
231
+		}
232
+		for(const char * const *r=elt->regs; *r; r++)
233
+		{
234
+			if(tlen && strncmp(text, *r, tlen))
235
+			{
236
+				continue;
237
+			}
238
+			if(!(ret[i] = strdup(*r)))
239
+			{
240
+				goto err_strdup;
241
+			}
242
+			if(argno == 0 && **r == '%')
243
+			{
244
+				//full match on arg0 adding ","
245
+				char *tmp = ret[i];
246
+				char buf[32];
247
+				snprintf(buf, 31, "%s,", tmp);
248
+				ret[i] = strdup(buf);
249
+			}
250
+			i++;
251
+		}
252
+	}
158 253
 	
159 254
 	return ret;
255
+
256
+err_strdup:
257
+	perror("Unable to strdup arg match");
258
+	i--;
259
+	while(i>=0)
260
+	{
261
+		free(ret[i]);
262
+		i--;
263
+	}
264
+err:
265
+	free(ret);
266
+	return NULL;
267
+
160 268
 }
161 269
 
162 270
 
@@ -261,3 +369,38 @@ static int _completion_upper_macro(const char *macro, const char *start, char **
261 369
 	return 1;
262 370
 }
263 371
 
372
+
373
+static int _completion_macro_match(const char *macro, const char *text, int mlen)
374
+{
375
+	char buf[32];
376
+	memcpy(buf, macro, mlen);
377
+	buf[mlen] = '\0';
378
+	switch(macro[mlen])
379
+	{
380
+		case 'C':
381
+			for(const char * const *cond = M_conds;*cond;cond++)
382
+			{
383
+				int ret=snprintf(&buf[mlen], 31-mlen, "%s", *cond);
384
+				int cmp = strncmp(text, buf, mlen+ret);
385
+				if(cmp ==  0)
386
+				{
387
+					return 0;
388
+				}
389
+			}
390
+			break;
391
+		case 'S':
392
+			for(const char * sz=M_sizes; *sz; sz++)
393
+			{
394
+				buf[mlen] = *sz;
395
+				buf[mlen+1] = '\0';
396
+				int cmp =  strncmp(text, buf, mlen+1);
397
+				if(cmp == 0)
398
+				{
399
+					return 0;
400
+				}
401
+			}
402
+			break;
403
+	}
404
+	return 1;
405
+}
406
+

+ 27
- 11
completion.h View File

@@ -73,6 +73,9 @@ static char *asmsh_rl_completion_gen(const char *text, int state)
73 73
 	}
74 74
 	return res;
75 75
 }
76
+extern int rl_attempted_completion_over;
77
+extern const char* rl_special_prefixes;
78
+extern const char* rl_basic_word_break_characters;
76 79
 static char **asmsh_rl_completion(const char *text, int start, int end)
77 80
 {
78 81
 	rl_attempted_completion_over = 1;
@@ -88,7 +91,7 @@ char **asmsh_compl_instr(const char *start);
88 91
 char **asmsh_compl_arg(const char *buf, const char *text, int start);
89 92
 
90 93
 static const char * const M_conds[] = {"o","no","b","c","nae","ae","nb","nc","e","z","ne","nz","be","na","a","nbe","s","ns","p","pe","np","po","l","nge","ge","nl","le","ng","g","nle", NULL};
91
-static const char *M_sizes = "bwdq";
94
+static const char M_sizes[] = "bwdq";
92 95
 /* Upper case letters are flags pointing to
93 96
  * more complex completion (like conditions)
94 97
  * C -> CMOVcc cc conditions
@@ -190,7 +193,8 @@ static const asmsh_compinstr_t x86_64_instr[] = {
190 193
 	{"outsb", 0, 0},
191 194
 	{"outsd", 0, 0},
192 195
 	{"outsw", 0, 0},
193
-	{"pop", 0xff, 0},
196
+	{"pop", ASHCOMP_REGALL, 0},
197
+	{"popS", ASHCOMP_IMM, 0},
194 198
 	{"popa", 0xff, 0},
195 199
 	{"popad", 0xff, 0},
196 200
 	{"popcnt", 0xff, 0xff},
@@ -201,6 +205,8 @@ static const asmsh_compinstr_t x86_64_instr[] = {
201 205
 	{"prefetch1", ASHCOMP_ADDR, 0},
202 206
 	{"prefetch2", ASHCOMP_ADDR, 0},
203 207
 	{"prefetchw", ASHCOMP_ADDR, 0},
208
+	{"push", ASHCOMP_REGALL, 0},
209
+	{"pushS", ASHCOMP_IMM, 0},
204 210
 	{"pusha", 0xff, 0},
205 211
 	{"pushad", 0xff, 0},
206 212
 	{"pushf", 0, 0},
@@ -244,32 +250,41 @@ static const asmsh_compinstr_t x86_64_instr[] = {
244 250
 };
245 251
 
246 252
 static const char * const asmsh_sym_regs64[] = {
247
-	"rax", "rbx", "rcx", "rdx", "rbp", "rsi", "rdi", "rsp",
248
-	"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
253
+	"%rax", "%rbx", "%rcx", "%rdx", "%rbp", "%rsi", "%rdi", "%rsp",
254
+	"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
255
+	NULL
249 256
 };
250 257
 static const char * const asmsh_sym_regs32[] = {
251
-	"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
258
+	"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
259
+	NULL
252 260
 };
253 261
 static const char * const asmsh_sym_regs16[] = {
254
-	"ax", "bx", "cx", "dx", "si", "di", "bp", "sp",
262
+	"%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
263
+	NULL
255 264
 };
256 265
 static const char * const asmsh_sym_regs8[] = {
257
-	"ah", "al", "bh", "bl", "ch", "cl", "dh", "dl"
266
+	"%ah", "%al", "%bh", "%bl", "%ch", "%cl", "%dh", "%dl",
267
+	NULL
258 268
 };
259 269
 static const char * const asmsh_sym_regsseg[] = {
260
-	"cs", "ds", "es", "fs", "gs", "ss",
270
+	"%cs", "%ds", "%es", "%fs", "%gs", "%ss",
271
+	NULL
261 272
 };
262 273
 static const char * const asmsh_sym_imm[] = {
263 274
 	"$", "$0x", "$0o",
275
+	NULL
264 276
 };
265 277
 static const char * const asmsh_sym_xmm[] = {
266
-	"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
278
+	"%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
279
+	NULL
267 280
 };
268 281
 static const char * const asmsh_sym_xmm2[] = {
269
-	"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
282
+	"%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15",
283
+	NULL
270 284
 };
271 285
 static const char * const asmsh_sym_ymm[] = {
272
-	"ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7",
286
+	"%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
287
+	NULL
273 288
 };
274 289
 
275 290
 typedef struct {
@@ -287,6 +302,7 @@ static const asmsh_symtable_elt_t asmsh_symtable[] = {
287 302
 	{ ASHCOMP_XMM, asmsh_sym_xmm},
288 303
 	{ ASHCOMP_XMM2, asmsh_sym_xmm2},
289 304
 	{ ASHCOMP_YMM, asmsh_sym_ymm},
305
+	{ 0, NULL },
290 306
 };
291 307
 
292 308
 #endif

Loading…
Cancel
Save