... | ... |
@@ -22,13 +22,6 @@ |
22 | 22 |
#define PLUGINNAME "prototypes" |
23 | 23 |
#define MAXINDEXDATALEN 1024 |
24 | 24 |
|
25 |
-typedef enum protolang_t { |
|
26 |
- protolang_undefined=-1, |
|
27 |
- protolang_c=0, |
|
28 |
- protolang_tcl, |
|
29 |
- protolang_end, |
|
30 |
-} protolang_t; |
|
31 |
- |
|
32 | 25 |
typedef struct protoindex_t { |
33 | 26 |
int nentries; |
34 | 27 |
const char **index; |
... | ... |
@@ -232,16 +225,8 @@ redata_prototypes_get(redata_t *redata, long pos) |
232 | 225 |
} status; |
233 | 226 |
if(redata==NULL || pos<0 || (cproto=cproto_getplugin(redata))==NULL) |
234 | 227 |
return(NULL); /* sanity check failed */ |
235 |
- if(cproto->lastprotolang==protolang_undefined) { |
|
236 |
- char linebuf[1024]; |
|
237 |
- if(redata_line_getstartstr(redata,0,linebuf,sizeof(linebuf))!=0) |
|
238 |
- return(NULL); /* couldn't detect file type using first line */ |
|
239 |
- if(linebuf[0]=='#' && (mystrstr(linebuf,"tclsh")!=NULL || mystrstr(linebuf,"wish")!=NULL || mystrstr(linebuf,"expect")!=NULL)) |
|
240 |
- cproto->lastprotolang=protolang_tcl; |
|
241 |
- else |
|
242 |
- cproto->lastprotolang=protolang_c; |
|
243 |
- cproto->lastpos=-1; |
|
244 |
- } |
|
228 |
+ if(cproto->lastprotolang==protolang_undefined) |
|
229 |
+ redata_prototypes_detectlang(redata); |
|
245 | 230 |
protoindex=cproto->protoindexes+cproto->lastprotolang; |
246 | 231 |
if(pos==cproto->lastpos) |
247 | 232 |
return((cproto->lastindex!=-1)?(protoindex->values[cproto->lastindex]):NULL); |
... | ... |
@@ -339,8 +324,22 @@ redata_prototypes_get(redata_t *redata, long pos) |
339 | 324 |
return(NULL); |
340 | 325 |
} |
341 | 326 |
|
342 |
- |
|
343 |
- |
|
327 |
+protolang_t |
|
328 |
+redata_prototypes_detectlang(redata_t *redata) |
|
329 |
+{ |
|
330 |
+ cproto_t *cproto; |
|
331 |
+ char linebuf[1024]; |
|
332 |
+ if(redata==NULL || (cproto=cproto_getplugin(redata))==NULL) |
|
333 |
+ return(protolang_undefined); /* sanity check failed */ |
|
334 |
+ if(redata_line_getstartstr(redata,0,linebuf,sizeof(linebuf))!=0) |
|
335 |
+ return(protolang_undefined); /* couldn't detect file type using first line */ |
|
336 |
+ if(linebuf[0]=='#' && (mystrstr(linebuf,"tclsh")!=NULL || mystrstr(linebuf,"wish")!=NULL || mystrstr(linebuf,"expect")!=NULL)) |
|
337 |
+ cproto->lastprotolang=protolang_tcl; |
|
338 |
+ else |
|
339 |
+ cproto->lastprotolang=protolang_c; |
|
340 |
+ cproto->lastpos=-1; |
|
341 |
+ return(cproto->lastprotolang); |
|
342 |
+} |
|
344 | 343 |
|
345 | 344 |
static int |
346 | 345 |
cproto_buffer_inv(cproto_t *cproto) |
... | ... |
@@ -17,17 +17,30 @@ |
17 | 17 |
#include "re_data.h" |
18 | 18 |
#include "re_plugin_prototypes.h" |
19 | 19 |
#include "prototypes_c89_posix.h" |
20 |
+#include "prototypes_tcl.h" |
|
20 | 21 |
|
21 | 22 |
#define PLUGINNAME "prototypes" |
22 | 23 |
#define MAXINDEXDATALEN 1024 |
23 | 24 |
|
25 |
+typedef enum protolang_t { |
|
26 |
+ protolang_undefined=-1, |
|
27 |
+ protolang_c=0, |
|
28 |
+ protolang_tcl, |
|
29 |
+ protolang_end, |
|
30 |
+} protolang_t; |
|
24 | 31 |
|
25 |
-typedef struct cproto_t { |
|
32 |
+typedef struct protoindex_t { |
|
26 | 33 |
int nentries; |
27 | 34 |
const char **index; |
28 | 35 |
const char **values; |
36 |
+} protoindex_t; |
|
37 |
+ |
|
38 |
+typedef struct cproto_t { |
|
39 |
+ int sizeprotoindexes; |
|
40 |
+ protoindex_t *protoindexes; |
|
29 | 41 |
long lastpos; |
30 | 42 |
int lastindex; |
43 |
+ protolang_t lastprotolang; |
|
31 | 44 |
int sizebuffer; |
32 | 45 |
int usedbuffer; |
33 | 46 |
char buffer[MAXINDEXDATALEN]; |
... | ... |
@@ -35,45 +48,21 @@ typedef struct cproto_t { |
35 | 48 |
|
36 | 49 |
static int redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); |
37 | 50 |
static int redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename); |
51 |
+static cproto_t *cproto_init(void); |
|
52 |
+static void cproto_free(cproto_t *cproto); |
|
38 | 53 |
static cproto_t *cproto_getplugin(redata_t *redata); |
39 | 54 |
static int cproto_buffer_inv(cproto_t *cproto); |
55 |
+const char *mystrstr(char *heystack, char *needle); |
|
40 | 56 |
static int cproto_buffer_getindex(cproto_t *cproto); |
41 | 57 |
|
42 | 58 |
int |
43 | 59 |
redata_prototypes_register(redata_t *redata, redata_plugin_t *slot) |
44 | 60 |
{ |
45 | 61 |
cproto_t *cproto; |
46 |
- const char *ptr; |
|
47 |
- int n; |
|
48 | 62 |
if(redata==NULL || slot==NULL) |
49 | 63 |
return(-1); |
50 |
- if((cproto=malloc(sizeof(cproto_t)))==NULL) |
|
51 |
- return(-1); /* insufficient memory */ |
|
52 |
- memset(cproto,0,sizeof(cproto_t)); |
|
53 |
- /* by default, we use C89/POSIX hints */ |
|
54 |
- cproto->nentries=SIZE_PROTOTYPES_C89_POSIX; |
|
55 |
- if((cproto->index=malloc(sizeof(char *)*cproto->nentries))==NULL |
|
56 |
- || (cproto->values=malloc(sizeof(char *)*cproto->nentries))==NULL) { |
|
57 |
- if(cproto->index!=NULL) |
|
58 |
- free(cproto->index),cproto->index=NULL; |
|
64 |
+ if((cproto=cproto_init())==NULL) |
|
59 | 65 |
return(-1); /* insufficient memory */ |
60 |
- } |
|
61 |
- memset(cproto->index,0,sizeof(char *)*cproto->nentries); |
|
62 |
- memset(cproto->values,0,sizeof(char *)*cproto->nentries); |
|
63 |
- for(n=0,ptr=index_prototypes_c89_posix |
|
64 |
- ;n<cproto->nentries |
|
65 |
- ;n++,ptr+=strlen(ptr)+1) { |
|
66 |
- cproto->index[n]=ptr; |
|
67 |
- } |
|
68 |
- for(n=0,ptr=values_prototypes_c89_posix |
|
69 |
- ;n<cproto->nentries |
|
70 |
- ;n++,ptr+=strlen(ptr)+1) { |
|
71 |
- cproto->values[n]=ptr; |
|
72 |
- } |
|
73 |
- cproto->lastpos=-1; |
|
74 |
- cproto->lastindex=-1; |
|
75 |
- cproto->usedbuffer=0; |
|
76 |
- cproto->sizebuffer=sizeof(cproto->buffer); |
|
77 | 66 |
strncpy(slot->name,PLUGINNAME,sizeof(slot->name)); |
78 | 67 |
slot->name[sizeof(slot->name)-1]='\0'; |
79 | 68 |
slot->unregister=redata_prototypes_unregister; |
... | ... |
@@ -89,12 +78,7 @@ redata_prototypes_unregister(redata_t *redata, redata_plugin_t *slot,char *filen |
89 | 78 |
cproto_t *cproto=(cproto_t *) ((slot!=NULL)?(slot->userptr):NULL); |
90 | 79 |
if(redata==NULL || slot==NULL || cproto==NULL) |
91 | 80 |
return(-1); |
92 |
- if(cproto->index!=NULL) |
|
93 |
- free(cproto->index),cproto->index=NULL; |
|
94 |
- if(cproto->values!=NULL) |
|
95 |
- free(cproto->values),cproto->values=NULL; |
|
96 |
- if(slot->userptr!=NULL) |
|
97 |
- free(slot->userptr),slot->userptr=NULL; |
|
81 |
+ cproto_free(cproto),cproto=NULL,slot->userptr=NULL; |
|
98 | 82 |
return(0); |
99 | 83 |
|
100 | 84 |
} |
... | ... |
@@ -108,6 +92,7 @@ redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t * |
108 | 92 |
return(-1); /* sanity check failed */ |
109 | 93 |
cproto->lastpos=-1; |
110 | 94 |
cproto->lastindex=-1; |
95 |
+ cproto->lastprotolang=protolang_undefined; |
|
111 | 96 |
return(0); |
112 | 97 |
} |
113 | 98 |
|
... | ... |
@@ -118,6 +103,81 @@ redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filenam |
118 | 103 |
return(-1); |
119 | 104 |
} |
120 | 105 |
|
106 |
+static cproto_t * |
|
107 |
+cproto_init(void) |
|
108 |
+{ |
|
109 |
+ int i; |
|
110 |
+ cproto_t *cproto; |
|
111 |
+ protoindex_t *protoindex; |
|
112 |
+ const char *ptrindex,*ptrvalues; |
|
113 |
+ int n; |
|
114 |
+ if((cproto=malloc(sizeof(cproto_t)))==NULL) |
|
115 |
+ return(NULL); /* insuf. mem. */ |
|
116 |
+ memset(cproto,0,sizeof(cproto_t)); |
|
117 |
+ /* initialize protoindexes */ |
|
118 |
+ if((cproto->protoindexes=malloc(sizeof(protoindex_t)*protolang_end))==NULL) { |
|
119 |
+ cproto_free(cproto),cproto=NULL; |
|
120 |
+ return(NULL); /* insuf. mem. */ |
|
121 |
+ } |
|
122 |
+ memset(cproto->protoindexes,0,sizeof(protoindex_t)*protolang_end); |
|
123 |
+ cproto->sizeprotoindexes=protolang_end; |
|
124 |
+ for(i=0;i<protolang_end;i++) { |
|
125 |
+ protoindex=cproto->protoindexes+i; |
|
126 |
+ if(i==protolang_c) { |
|
127 |
+ protoindex->nentries=SIZE_PROTOTYPES_C89_POSIX; |
|
128 |
+ ptrindex=index_prototypes_c89_posix; |
|
129 |
+ ptrvalues=values_prototypes_c89_posix; |
|
130 |
+ } else if(i==protolang_tcl) { |
|
131 |
+ protoindex->nentries=SIZE_PROTOTYPES_TCL; |
|
132 |
+ ptrindex=index_prototypes_tcl; |
|
133 |
+ ptrvalues=values_prototypes_tcl; |
|
134 |
+ } else { |
|
135 |
+ cproto_free(cproto),cproto=NULL; |
|
136 |
+ return(NULL); /* internal error, unknown protolang */ |
|
137 |
+ } |
|
138 |
+ if((protoindex->index=malloc(sizeof(char *)*protoindex->nentries))==NULL |
|
139 |
+ || (protoindex->values=malloc(sizeof(char *)*protoindex->nentries))==NULL) { |
|
140 |
+ cproto_free(cproto),cproto=NULL; |
|
141 |
+ return(NULL); /* insufficient memory */ |
|
142 |
+ } |
|
143 |
+ memset(protoindex->index,0,sizeof(char *)*protoindex->nentries); |
|
144 |
+ memset(protoindex->values,0,sizeof(char *)*protoindex->nentries); |
|
145 |
+ for(n=0;n<protoindex->nentries |
|
146 |
+ ;n++,ptrindex+=strlen(ptrindex)+1,ptrvalues+=strlen(ptrvalues)+1) { |
|
147 |
+ protoindex->index[n]=ptrindex; |
|
148 |
+ protoindex->values[n]=ptrvalues; |
|
149 |
+ } |
|
150 |
+ } |
|
151 |
+ /* init caches */ |
|
152 |
+ cproto->lastpos=-1; |
|
153 |
+ cproto->lastindex=-1; |
|
154 |
+ cproto->lastprotolang=protolang_undefined; |
|
155 |
+ cproto->usedbuffer=0; |
|
156 |
+ cproto->sizebuffer=sizeof(cproto->buffer); |
|
157 |
+ return(cproto); |
|
158 |
+} |
|
159 |
+ |
|
160 |
+static void |
|
161 |
+cproto_free(cproto_t *cproto) |
|
162 |
+{ |
|
163 |
+ int i; |
|
164 |
+ if(cproto==NULL) |
|
165 |
+ return; |
|
166 |
+ if(cproto->protoindexes!=NULL) { |
|
167 |
+ protoindex_t *protoindex; |
|
168 |
+ for(i=0;i<cproto->sizeprotoindexes;i++) { |
|
169 |
+ protoindex=cproto->protoindexes+i; |
|
170 |
+ if(protoindex->index!=NULL) |
|
171 |
+ free(protoindex->index),protoindex->index=NULL; |
|
172 |
+ if(protoindex->values!=NULL) |
|
173 |
+ free(protoindex->values),protoindex->values=NULL; |
|
174 |
+ } |
|
175 |
+ free(cproto->protoindexes),cproto->protoindexes=NULL; |
|
176 |
+ } |
|
177 |
+ free(cproto),cproto=NULL; |
|
178 |
+ return; |
|
179 |
+} |
|
180 |
+ |
|
121 | 181 |
static cproto_t * |
122 | 182 |
cproto_getplugin(redata_t *redata) |
123 | 183 |
{ |
... | ... |
@@ -137,6 +197,20 @@ cproto_getplugin(redata_t *redata) |
137 | 197 |
return(cproto); |
138 | 198 |
} |
139 | 199 |
|
200 |
+const char * |
|
201 |
+mystrstr(char *haystack, char *needle) |
|
202 |
+{ |
|
203 |
+ char *ptr; |
|
204 |
+ int l; |
|
205 |
+ if(needle[0]=='\0') |
|
206 |
+ return(haystack); |
|
207 |
+ l=strlen(needle); |
|
208 |
+ for(ptr=strchr(haystack,needle[0]);ptr!=NULL;ptr=strchr(ptr+1,needle[0])) { |
|
209 |
+ if(memcmp(ptr,needle,l)==0) |
|
210 |
+ return(ptr); |
|
211 |
+ } |
|
212 |
+ return(NULL); |
|
213 |
+} |
|
140 | 214 |
|
141 | 215 |
const char * |
142 | 216 |
redata_prototypes_get(redata_t *redata, long pos) |
... | ... |
@@ -146,6 +220,7 @@ redata_prototypes_get(redata_t *redata, long pos) |
146 | 220 |
long chunkstartpos; |
147 | 221 |
rechunk_t *chunk; |
148 | 222 |
cproto_t *cproto; |
223 |
+ protoindex_t *protoindex; |
|
149 | 224 |
char c; |
150 | 225 |
int ntry; |
151 | 226 |
enum { |
... | ... |
@@ -157,8 +232,19 @@ redata_prototypes_get(redata_t *redata, long pos) |
157 | 232 |
} status; |
158 | 233 |
if(redata==NULL || pos<0 || (cproto=cproto_getplugin(redata))==NULL) |
159 | 234 |
return(NULL); /* sanity check failed */ |
235 |
+ if(cproto->lastprotolang==protolang_undefined) { |
|
236 |
+ char linebuf[1024]; |
|
237 |
+ if(redata_line_getstartstr(redata,0,linebuf,sizeof(linebuf))!=0) |
|
238 |
+ return(NULL); /* couldn't detect file type using first line */ |
|
239 |
+ if(linebuf[0]=='#' && (mystrstr(linebuf,"tclsh")!=NULL || mystrstr(linebuf,"wish")!=NULL || mystrstr(linebuf,"expect")!=NULL)) |
|
240 |
+ cproto->lastprotolang=protolang_tcl; |
|
241 |
+ else |
|
242 |
+ cproto->lastprotolang=protolang_c; |
|
243 |
+ cproto->lastpos=-1; |
|
244 |
+ } |
|
245 |
+ protoindex=cproto->protoindexes+cproto->lastprotolang; |
|
160 | 246 |
if(pos==cproto->lastpos) |
161 |
- return((cproto->lastindex!=-1)?(cproto->values[cproto->lastindex]):NULL); |
|
247 |
+ return((cproto->lastindex!=-1)?(protoindex->values[cproto->lastindex]):NULL); |
|
162 | 248 |
if(redata_getposptr(redata,pos,&savednumchunk,&savedoffset)!=0) |
163 | 249 |
return(NULL); /* couldn't get pos */ |
164 | 250 |
cproto->lastpos=pos; |
... | ... |
@@ -224,12 +310,12 @@ redata_prototypes_get(redata_t *redata, long pos) |
224 | 310 |
cproto_buffer_inv(cproto); |
225 | 311 |
/* search string */ |
226 | 312 |
if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) |
227 |
- return(cproto->values[cproto->lastindex]); |
|
313 |
+ return(protoindex->values[cproto->lastindex]); |
|
228 | 314 |
} |
229 | 315 |
cproto->usedbuffer=0; |
230 | 316 |
status=searching_nameend; |
231 | 317 |
continue; |
232 |
- } else if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) { |
|
318 |
+ } else if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_' || (cproto->lastprotolang==protolang_tcl && c==' '))) { |
|
233 | 319 |
status=searching_ended; |
234 | 320 |
break; |
235 | 321 |
} else { |
... | ... |
@@ -240,10 +326,14 @@ redata_prototypes_get(redata_t *redata, long pos) |
240 | 326 |
} |
241 | 327 |
} |
242 | 328 |
if((status==searching_nameend || status==searching_ended) && cproto->usedbuffer>0) { |
329 |
+ /* trim spaces leading to word (for tcl) */ |
|
330 |
+ while(cproto->usedbuffer>0 && cproto->buffer[cproto->usedbuffer-1]==' ') |
|
331 |
+ cproto->usedbuffer--; |
|
332 |
+ /* put the string in the correct order */ |
|
243 | 333 |
cproto_buffer_inv(cproto); |
244 | 334 |
/* search string */ |
245 | 335 |
if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) |
246 |
- return(cproto->values[cproto->lastindex]); |
|
336 |
+ return(protoindex->values[cproto->lastindex]); |
|
247 | 337 |
} |
248 | 338 |
} |
249 | 339 |
return(NULL); |
... | ... |
@@ -277,13 +367,14 @@ cproto_buffer_getindex(cproto_t *cproto) |
277 | 367 |
{ |
278 | 368 |
#warning TODO use qsearch() |
279 | 369 |
int i; |
370 |
+ protoindex_t *protoindex; |
|
280 | 371 |
if(cproto==NULL) |
281 | 372 |
return(-1); |
282 | 373 |
cproto->buffer[cproto->usedbuffer]='\0'; |
283 |
- for(i=0;i<cproto->nentries;i++) { |
|
284 |
- if(strcmp(cproto->index[i],cproto->buffer)==0) { |
|
374 |
+ protoindex=cproto->protoindexes+cproto->lastprotolang; |
|
375 |
+ for(i=0;i<protoindex->nentries;i++) { |
|
376 |
+ if(strcmp(protoindex->index[i],cproto->buffer)==0) |
|
285 | 377 |
return(i); |
286 |
- } |
|
287 | 378 |
} |
288 | 379 |
return(-1); |
289 | 380 |
} |
... | ... |
@@ -197,7 +197,7 @@ redata_prototypes_get(redata_t *redata, long pos) |
197 | 197 |
chunk=redata->chunks[numchunk]; |
198 | 198 |
for(;offset>=0;offset--) { |
199 | 199 |
c=chunk->data[offset]; |
200 |
- if(c=='\n') { |
|
200 |
+ if(c=='\n' && !(numchunk==savednumchunk && offset==savedoffset)) { |
|
201 | 201 |
status=searching_ended; |
202 | 202 |
break; |
203 | 203 |
} |
... | ... |
@@ -33,8 +33,6 @@ typedef struct cproto_t { |
33 | 33 |
char buffer[MAXINDEXDATALEN]; |
34 | 34 |
} cproto_t; |
35 | 35 |
|
36 |
-static int redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
37 |
-static int redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
38 | 36 |
static int redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); |
39 | 37 |
static int redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename); |
40 | 38 |
static cproto_t *cproto_getplugin(redata_t *redata); |
... | ... |
@@ -80,8 +78,7 @@ redata_prototypes_register(redata_t *redata, redata_plugin_t *slot) |
80 | 78 |
slot->name[sizeof(slot->name)-1]='\0'; |
81 | 79 |
slot->unregister=redata_prototypes_unregister; |
82 | 80 |
slot->postload=redata_prototypes_postload; |
83 |
- slot->add=redata_prototypes_add; |
|
84 |
- slot->unadd=redata_prototypes_unadd; |
|
81 |
+ slot->add_or_unadd=redata_prototypes_add_or_unadd; |
|
85 | 82 |
slot->userptr=cproto; |
86 | 83 |
return(0); |
87 | 84 |
} |
... | ... |
@@ -102,19 +99,6 @@ redata_prototypes_unregister(redata_t *redata, redata_plugin_t *slot,char *filen |
102 | 99 |
|
103 | 100 |
} |
104 | 101 |
|
105 |
-static int |
|
106 |
-redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
107 |
-{ |
|
108 |
- return(redata_prototypes_add_or_unadd(redata, slot, undo, 0)); |
|
109 |
-} |
|
110 |
- |
|
111 |
-static int |
|
112 |
-redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
113 |
-{ |
|
114 |
- return(redata_prototypes_add_or_unadd(redata, slot, undo, 1)); |
|
115 |
-} |
|
116 |
- |
|
117 |
- |
|
118 | 102 |
static int |
119 | 103 |
redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd) |
120 | 104 |
{ |
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,305 @@ |
1 |
+/* |
|
2 |
+ * re_plugin_prototypes.c |
|
3 |
+ * |
|
4 |
+ * A programmers editor |
|
5 |
+ * |
|
6 |
+ * re_data plugin to support showing common prototypes hints. |
|
7 |
+ * |
|
8 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
9 |
+ * This program is licensed under the terms of GNU GPL v2.1+ |
|
10 |
+ */ |
|
11 |
+ |
|
12 |
+#include <stdio.h> |
|
13 |
+#include <stdlib.h> |
|
14 |
+#include <unistd.h> |
|
15 |
+#include <string.h> |
|
16 |
+ |
|
17 |
+#include "re_data.h" |
|
18 |
+#include "re_plugin_prototypes.h" |
|
19 |
+#include "prototypes_c89_posix.h" |
|
20 |
+ |
|
21 |
+#define PLUGINNAME "prototypes" |
|
22 |
+#define MAXINDEXDATALEN 1024 |
|
23 |
+ |
|
24 |
+ |
|
25 |
+typedef struct cproto_t { |
|
26 |
+ int nentries; |
|
27 |
+ const char **index; |
|
28 |
+ const char **values; |
|
29 |
+ long lastpos; |
|
30 |
+ int lastindex; |
|
31 |
+ int sizebuffer; |
|
32 |
+ int usedbuffer; |
|
33 |
+ char buffer[MAXINDEXDATALEN]; |
|
34 |
+} cproto_t; |
|
35 |
+ |
|
36 |
+static int redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
37 |
+static int redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
38 |
+static int redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); |
|
39 |
+static int redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename); |
|
40 |
+static cproto_t *cproto_getplugin(redata_t *redata); |
|
41 |
+static int cproto_buffer_inv(cproto_t *cproto); |
|
42 |
+static int cproto_buffer_getindex(cproto_t *cproto); |
|
43 |
+ |
|
44 |
+int |
|
45 |
+redata_prototypes_register(redata_t *redata, redata_plugin_t *slot) |
|
46 |
+{ |
|
47 |
+ cproto_t *cproto; |
|
48 |
+ const char *ptr; |
|
49 |
+ int n; |
|
50 |
+ if(redata==NULL || slot==NULL) |
|
51 |
+ return(-1); |
|
52 |
+ if((cproto=malloc(sizeof(cproto_t)))==NULL) |
|
53 |
+ return(-1); /* insufficient memory */ |
|
54 |
+ memset(cproto,0,sizeof(cproto_t)); |
|
55 |
+ /* by default, we use C89/POSIX hints */ |
|
56 |
+ cproto->nentries=SIZE_PROTOTYPES_C89_POSIX; |
|
57 |
+ if((cproto->index=malloc(sizeof(char *)*cproto->nentries))==NULL |
|
58 |
+ || (cproto->values=malloc(sizeof(char *)*cproto->nentries))==NULL) { |
|
59 |
+ if(cproto->index!=NULL) |
|
60 |
+ free(cproto->index),cproto->index=NULL; |
|
61 |
+ return(-1); /* insufficient memory */ |
|
62 |
+ } |
|
63 |
+ memset(cproto->index,0,sizeof(char *)*cproto->nentries); |
|
64 |
+ memset(cproto->values,0,sizeof(char *)*cproto->nentries); |
|
65 |
+ for(n=0,ptr=index_prototypes_c89_posix |
|
66 |
+ ;n<cproto->nentries |
|
67 |
+ ;n++,ptr+=strlen(ptr)+1) { |
|
68 |
+ cproto->index[n]=ptr; |
|
69 |
+ } |
|
70 |
+ for(n=0,ptr=values_prototypes_c89_posix |
|
71 |
+ ;n<cproto->nentries |
|
72 |
+ ;n++,ptr+=strlen(ptr)+1) { |
|
73 |
+ cproto->values[n]=ptr; |
|
74 |
+ } |
|
75 |
+ cproto->lastpos=-1; |
|
76 |
+ cproto->lastindex=-1; |
|
77 |
+ cproto->usedbuffer=0; |
|
78 |
+ cproto->sizebuffer=sizeof(cproto->buffer); |
|
79 |
+ strncpy(slot->name,PLUGINNAME,sizeof(slot->name)); |
|
80 |
+ slot->name[sizeof(slot->name)-1]='\0'; |
|
81 |
+ slot->unregister=redata_prototypes_unregister; |
|
82 |
+ slot->postload=redata_prototypes_postload; |
|
83 |
+ slot->add=redata_prototypes_add; |
|
84 |
+ slot->unadd=redata_prototypes_unadd; |
|
85 |
+ slot->userptr=cproto; |
|
86 |
+ return(0); |
|
87 |
+} |
|
88 |
+ |
|
89 |
+int |
|
90 |
+redata_prototypes_unregister(redata_t *redata, redata_plugin_t *slot,char *filename) |
|
91 |
+{ |
|
92 |
+ cproto_t *cproto=(cproto_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
93 |
+ if(redata==NULL || slot==NULL || cproto==NULL) |
|
94 |
+ return(-1); |
|
95 |
+ if(cproto->index!=NULL) |
|
96 |
+ free(cproto->index),cproto->index=NULL; |
|
97 |
+ if(cproto->values!=NULL) |
|
98 |
+ free(cproto->values),cproto->values=NULL; |
|
99 |
+ if(slot->userptr!=NULL) |
|
100 |
+ free(slot->userptr),slot->userptr=NULL; |
|
101 |
+ return(0); |
|
102 |
+ |
|
103 |
+} |
|
104 |
+ |
|
105 |
+static int |
|
106 |
+redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
107 |
+{ |
|
108 |
+ return(redata_prototypes_add_or_unadd(redata, slot, undo, 0)); |
|
109 |
+} |
|
110 |
+ |
|
111 |
+static int |
|
112 |
+redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
113 |
+{ |
|
114 |
+ return(redata_prototypes_add_or_unadd(redata, slot, undo, 1)); |
|
115 |
+} |
|
116 |
+ |
|
117 |
+ |
|
118 |
+static int |
|
119 |
+redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd) |
|
120 |
+{ |
|
121 |
+ /* reset the cache */ |
|
122 |
+ cproto_t *cproto=(cproto_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
123 |
+ if(redata==NULL || slot==NULL || cproto==NULL || undo==NULL || slot->active==0) |
|
124 |
+ return(-1); /* sanity check failed */ |
|
125 |
+ cproto->lastpos=-1; |
|
126 |
+ cproto->lastindex=-1; |
|
127 |
+ return(0); |
|
128 |
+} |
|
129 |
+ |
|
130 |
+static int |
|
131 |
+redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename) |
|
132 |
+{ |
|
133 |
+#warning XXX TODO: get the language from the filename |
|
134 |
+ return(-1); |
|
135 |
+} |
|
136 |
+ |
|
137 |
+static cproto_t * |
|
138 |
+cproto_getplugin(redata_t *redata) |
|
139 |
+{ |
|
140 |
+ cproto_t *cproto; |
|
141 |
+ int i; |
|
142 |
+ if(redata==NULL) |
|
143 |
+ return(NULL); /* sanity check failed */ |
|
144 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
145 |
+ if(strcmp(redata->plugins[i].name,PLUGINNAME)==0) |
|
146 |
+ break; |
|
147 |
+ } |
|
148 |
+ if(i>=redata->sizeplugins || redata->plugins[i].active==0) |
|
149 |
+ return(NULL); /* plugin not found or nor active */ |
|
150 |
+ cproto=(cproto_t *) (redata->plugins[i].userptr); |
|
151 |
+ if(cproto==NULL) |
|
152 |
+ return(NULL); /* internal error */ |
|
153 |
+ return(cproto); |
|
154 |
+} |
|
155 |
+ |
|
156 |
+ |
|
157 |
+const char * |
|
158 |
+redata_prototypes_get(redata_t *redata, long pos) |
|
159 |
+{ |
|
160 |
+ int numchunk,savednumchunk; |
|
161 |
+ int offset,savedoffset; |
|
162 |
+ long chunkstartpos; |
|
163 |
+ rechunk_t *chunk; |
|
164 |
+ cproto_t *cproto; |
|
165 |
+ char c; |
|
166 |
+ int ntry; |
|
167 |
+ enum { |
|
168 |
+ searching_forward, |
|
169 |
+ searching_paren, |
|
170 |
+ searching_name, |
|
171 |
+ searching_nameend, |
|
172 |
+ searching_ended, |
|
173 |
+ } status; |
|
174 |
+ if(redata==NULL || pos<0 || (cproto=cproto_getplugin(redata))==NULL) |
|
175 |
+ return(NULL); /* sanity check failed */ |
|
176 |
+ if(pos==cproto->lastpos) |
|
177 |
+ return((cproto->lastindex!=-1)?(cproto->values[cproto->lastindex]):NULL); |
|
178 |
+ if(redata_getposptr(redata,pos,&savednumchunk,&savedoffset)!=0) |
|
179 |
+ return(NULL); /* couldn't get pos */ |
|
180 |
+ cproto->lastpos=pos; |
|
181 |
+ cproto->lastindex=-1; |
|
182 |
+ /* FIRST TRY: check if current word is in index */ |
|
183 |
+ /* SECOND TRY: check if word before the last '( is in index */ |
|
184 |
+ for(ntry=0;ntry<2;ntry++) { |
|
185 |
+ numchunk=savednumchunk; |
|
186 |
+ offset=savedoffset; |
|
187 |
+ chunkstartpos=pos-offset; |
|
188 |
+ status=(ntry==0)?searching_forward:searching_paren; |
|
189 |
+ cproto->usedbuffer=0; |
|
190 |
+ /* search forward for current word end */ |
|
191 |
+ if(ntry==0) { |
|
192 |
+ for(;status==searching_forward && numchunk<redata->sizechunks |
|
193 |
+ ;chunkstartpos+=chunk->useddata,numchunk++,offset=0) { |
|
194 |
+ chunk=redata->chunks[numchunk]; |
|
195 |
+ for(;offset<chunk->useddata;offset++) { |
|
196 |
+ c=chunk->data[offset]; |
|
197 |
+ if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) { |
|
198 |
+ status=searching_name; |
|
199 |
+ break; |
|
200 |
+ } |
|
201 |
+ } |
|
202 |
+ if(status!=searching_forward) |
|
203 |
+ break; |
|
204 |
+ } |
|
205 |
+ } |
|
206 |
+ if(ntry==0 && status!=searching_name) |
|
207 |
+ continue; |
|
208 |
+ /* search backwards for prototype info */ |
|
209 |
+ for(;numchunk>=0 && status!=searching_ended |
|
210 |
+ ;numchunk-- |
|
211 |
+ ,offset=(numchunk>=0)?redata->chunks[numchunk]->useddata-1:0 |
|
212 |
+ ,chunkstartpos-=(numchunk>=0)?redata->chunks[numchunk]->useddata:0) { |
|
213 |
+ chunk=redata->chunks[numchunk]; |
|
214 |
+ for(;offset>=0;offset--) { |
|
215 |
+ c=chunk->data[offset]; |
|
216 |
+ if(c=='\n') { |
|
217 |
+ status=searching_ended; |
|
218 |
+ break; |
|
219 |
+ } |
|
220 |
+ if(status==searching_paren) { |
|
221 |
+ if(c=='(') { |
|
222 |
+ status=searching_name; |
|
223 |
+ continue; |
|
224 |
+ |
|
225 |
+ } |
|
226 |
+ } else if(status==searching_name) { |
|
227 |
+ if(c==')') { |
|
228 |
+ status=searching_paren; |
|
229 |
+ continue; |
|
230 |
+ } |
|
231 |
+ if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_') { |
|
232 |
+ cproto->usedbuffer=0; |
|
233 |
+ cproto->buffer[(cproto->usedbuffer++)]=c; |
|
234 |
+ status=searching_nameend; |
|
235 |
+ } |
|
236 |
+ } else { /* status==searching_nameend */ |
|
237 |
+ if(c=='(') { |
|
238 |
+ if(cproto->usedbuffer>0) { |
|
239 |
+ /* if we had a hit, return that */ |
|
240 |
+ cproto_buffer_inv(cproto); |
|
241 |
+ /* search string */ |
|
242 |
+ if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) |
|
243 |
+ return(cproto->values[cproto->lastindex]); |
|
244 |
+ } |
|
245 |
+ cproto->usedbuffer=0; |
|
246 |
+ status=searching_nameend; |
|
247 |
+ continue; |
|
248 |
+ } else if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) { |
|
249 |
+ status=searching_ended; |
|
250 |
+ break; |
|
251 |
+ } else { |
|
252 |
+ if((cproto->usedbuffer+1)<cproto->sizebuffer) |
|
253 |
+ cproto->buffer[(cproto->usedbuffer++)]=c; |
|
254 |
+ } |
|
255 |
+ } |
|
256 |
+ } |
|
257 |
+ } |
|
258 |
+ if((status==searching_nameend || status==searching_ended) && cproto->usedbuffer>0) { |
|
259 |
+ cproto_buffer_inv(cproto); |
|
260 |
+ /* search string */ |
|
261 |
+ if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) |
|
262 |
+ return(cproto->values[cproto->lastindex]); |
|
263 |
+ } |
|
264 |
+ } |
|
265 |
+ return(NULL); |
|
266 |
+} |
|
267 |
+ |
|
268 |
+ |
|
269 |
+ |
|
270 |
+ |
|
271 |
+static int |
|
272 |
+cproto_buffer_inv(cproto_t *cproto) |
|
273 |
+{ |
|
274 |
+ int i,l,l2; |
|
275 |
+ char c; |
|
276 |
+ if(cproto==NULL) |
|
277 |
+ return(-1); |
|
278 |
+ /* terminate string */ |
|
279 |
+ cproto->buffer[cproto->usedbuffer]='\0'; |
|
280 |
+ /* invert string */ |
|
281 |
+ l=cproto->usedbuffer; |
|
282 |
+ l2=l>>1; |
|
283 |
+ for(i=0;i<l2;i++) { |
|
284 |
+ c=cproto->buffer[i]; |
|
285 |
+ cproto->buffer[i]=cproto->buffer[l-1-i]; |
|
286 |
+ cproto->buffer[l-1-i]=c; |
|
287 |
+ } |
|
288 |
+ return(0); |
|
289 |
+} |
|
290 |
+ |
|
291 |
+static int |
|
292 |
+cproto_buffer_getindex(cproto_t *cproto) |
|
293 |
+{ |
|
294 |
+#warning TODO use qsearch() |
|
295 |
+ int i; |
|
296 |
+ if(cproto==NULL) |
|
297 |
+ return(-1); |
|
298 |
+ cproto->buffer[cproto->usedbuffer]='\0'; |
|
299 |
+ for(i=0;i<cproto->nentries;i++) { |
|
300 |
+ if(strcmp(cproto->index[i],cproto->buffer)==0) { |
|
301 |
+ return(i); |
|
302 |
+ } |
|
303 |
+ } |
|
304 |
+ return(-1); |
|
305 |
+} |