/* * re_plugin_prototypes.c * * A programmers editor * * re_data plugin to support showing common prototypes hints. * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of GNU GPL v2.1+ */ #include #include #include #include #include "re_data.h" #include "re_plugin_prototypes.h" #include "prototypes_c89_posix.h" #define PLUGINNAME "prototypes" #define MAXINDEXDATALEN 1024 typedef struct cproto_t { int nentries; const char **index; const char **values; long lastpos; int lastindex; int sizebuffer; int usedbuffer; char buffer[MAXINDEXDATALEN]; } cproto_t; static int redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); static int redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); static int redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); static int redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename); static cproto_t *cproto_getplugin(redata_t *redata); static int cproto_buffer_inv(cproto_t *cproto); static int cproto_buffer_getindex(cproto_t *cproto); int redata_prototypes_register(redata_t *redata, redata_plugin_t *slot) { cproto_t *cproto; const char *ptr; int n; if(redata==NULL || slot==NULL) return(-1); if((cproto=malloc(sizeof(cproto_t)))==NULL) return(-1); /* insufficient memory */ memset(cproto,0,sizeof(cproto_t)); /* by default, we use C89/POSIX hints */ cproto->nentries=SIZE_PROTOTYPES_C89_POSIX; if((cproto->index=malloc(sizeof(char *)*cproto->nentries))==NULL || (cproto->values=malloc(sizeof(char *)*cproto->nentries))==NULL) { if(cproto->index!=NULL) free(cproto->index),cproto->index=NULL; return(-1); /* insufficient memory */ } memset(cproto->index,0,sizeof(char *)*cproto->nentries); memset(cproto->values,0,sizeof(char *)*cproto->nentries); for(n=0,ptr=index_prototypes_c89_posix ;nnentries ;n++,ptr+=strlen(ptr)+1) { cproto->index[n]=ptr; } for(n=0,ptr=values_prototypes_c89_posix ;nnentries ;n++,ptr+=strlen(ptr)+1) { cproto->values[n]=ptr; } cproto->lastpos=-1; cproto->lastindex=-1; cproto->usedbuffer=0; cproto->sizebuffer=sizeof(cproto->buffer); strncpy(slot->name,PLUGINNAME,sizeof(slot->name)); slot->name[sizeof(slot->name)-1]='\0'; slot->unregister=redata_prototypes_unregister; slot->postload=redata_prototypes_postload; slot->add=redata_prototypes_add; slot->unadd=redata_prototypes_unadd; slot->userptr=cproto; return(0); } int redata_prototypes_unregister(redata_t *redata, redata_plugin_t *slot,char *filename) { cproto_t *cproto=(cproto_t *) ((slot!=NULL)?(slot->userptr):NULL); if(redata==NULL || slot==NULL || cproto==NULL) return(-1); if(cproto->index!=NULL) free(cproto->index),cproto->index=NULL; if(cproto->values!=NULL) free(cproto->values),cproto->values=NULL; if(slot->userptr!=NULL) free(slot->userptr),slot->userptr=NULL; return(0); } static int redata_prototypes_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) { return(redata_prototypes_add_or_unadd(redata, slot, undo, 0)); } static int redata_prototypes_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) { return(redata_prototypes_add_or_unadd(redata, slot, undo, 1)); } static int redata_prototypes_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd) { /* reset the cache */ cproto_t *cproto=(cproto_t *) ((slot!=NULL)?(slot->userptr):NULL); if(redata==NULL || slot==NULL || cproto==NULL || undo==NULL || slot->active==0) return(-1); /* sanity check failed */ cproto->lastpos=-1; cproto->lastindex=-1; return(0); } static int redata_prototypes_postload(redata_t *redata, redata_plugin_t *slot,char *filename) { #warning XXX TODO: get the language from the filename return(-1); } static cproto_t * cproto_getplugin(redata_t *redata) { cproto_t *cproto; int i; if(redata==NULL) return(NULL); /* sanity check failed */ for(i=0;isizeplugins;i++) { if(strcmp(redata->plugins[i].name,PLUGINNAME)==0) break; } if(i>=redata->sizeplugins || redata->plugins[i].active==0) return(NULL); /* plugin not found or nor active */ cproto=(cproto_t *) (redata->plugins[i].userptr); if(cproto==NULL) return(NULL); /* internal error */ return(cproto); } const char * redata_prototypes_get(redata_t *redata, long pos) { int numchunk,savednumchunk; int offset,savedoffset; long chunkstartpos; rechunk_t *chunk; cproto_t *cproto; char c; int ntry; enum { searching_forward, searching_paren, searching_name, searching_nameend, searching_ended, } status; if(redata==NULL || pos<0 || (cproto=cproto_getplugin(redata))==NULL) return(NULL); /* sanity check failed */ if(pos==cproto->lastpos) return((cproto->lastindex!=-1)?(cproto->values[cproto->lastindex]):NULL); if(redata_getposptr(redata,pos,&savednumchunk,&savedoffset)!=0) return(NULL); /* couldn't get pos */ cproto->lastpos=pos; cproto->lastindex=-1; /* FIRST TRY: check if current word is in index */ /* SECOND TRY: check if word before the last '( is in index */ for(ntry=0;ntry<2;ntry++) { numchunk=savednumchunk; offset=savedoffset; chunkstartpos=pos-offset; status=(ntry==0)?searching_forward:searching_paren; cproto->usedbuffer=0; /* search forward for current word end */ if(ntry==0) { for(;status==searching_forward && numchunksizechunks ;chunkstartpos+=chunk->useddata,numchunk++,offset=0) { chunk=redata->chunks[numchunk]; for(;offsetuseddata;offset++) { c=chunk->data[offset]; if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) { status=searching_name; break; } } if(status!=searching_forward) break; } } if(ntry==0 && status!=searching_name) continue; /* search backwards for prototype info */ for(;numchunk>=0 && status!=searching_ended ;numchunk-- ,offset=(numchunk>=0)?redata->chunks[numchunk]->useddata-1:0 ,chunkstartpos-=(numchunk>=0)?redata->chunks[numchunk]->useddata:0) { chunk=redata->chunks[numchunk]; for(;offset>=0;offset--) { c=chunk->data[offset]; if(c=='\n') { status=searching_ended; break; } if(status==searching_paren) { if(c=='(') { status=searching_name; continue; } } else if(status==searching_name) { if(c==')') { status=searching_paren; continue; } if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_') { cproto->usedbuffer=0; cproto->buffer[(cproto->usedbuffer++)]=c; status=searching_nameend; } } else { /* status==searching_nameend */ if(c=='(') { if(cproto->usedbuffer>0) { /* if we had a hit, return that */ cproto_buffer_inv(cproto); /* search string */ if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) return(cproto->values[cproto->lastindex]); } cproto->usedbuffer=0; status=searching_nameend; continue; } else if(!((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) { status=searching_ended; break; } else { if((cproto->usedbuffer+1)sizebuffer) cproto->buffer[(cproto->usedbuffer++)]=c; } } } } if((status==searching_nameend || status==searching_ended) && cproto->usedbuffer>0) { cproto_buffer_inv(cproto); /* search string */ if((cproto->lastindex=cproto_buffer_getindex(cproto))!=-1) return(cproto->values[cproto->lastindex]); } } return(NULL); } static int cproto_buffer_inv(cproto_t *cproto) { int i,l,l2; char c; if(cproto==NULL) return(-1); /* terminate string */ cproto->buffer[cproto->usedbuffer]='\0'; /* invert string */ l=cproto->usedbuffer; l2=l>>1; for(i=0;ibuffer[i]; cproto->buffer[i]=cproto->buffer[l-1-i]; cproto->buffer[l-1-i]=c; } return(0); } static int cproto_buffer_getindex(cproto_t *cproto) { #warning TODO use qsearch() int i; if(cproto==NULL) return(-1); cproto->buffer[cproto->usedbuffer]='\0'; for(i=0;inentries;i++) { if(strcmp(cproto->index[i],cproto->buffer)==0) { return(i); } } return(-1); }