| ... | ... |
@@ -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 |
+} |