#include #include #include #include #include #include #include #include "proto.h" #include "proto.m" /* Initialise une structure CPLUS pour recevoir des prototypes */ void cplus_init (CPLUS *cp, int size) { cp->nbcls = cp->nbdecl = 0; cp->cur = NULL; cp->cls = (CPLUS_CLS*)calloc_err (1000,sizeof(CPLUS_CLS),1); cp->decl = (CPLUS_DECL*)calloc_err (2000,sizeof(CPLUS_DECL),1); cp->alloc = (char*) malloc_err (size+1,1); /* Alloue jamais 0 */ cp->ptalloc = cp->alloc; } /* Libere espace associé à une liste de prototypes */ void cplus_end (CPLUS *cp) { free (cp->cls); free (cp->decl); free (cp->alloc); cp->nbcls = cp->nbdecl = 0; cp->cur = NULL; } /* Sélectionne la classe courante et l'accumulateur de déclaration */ static void cplus_select (CPLUS *cp, const char *nomcls) { int i; CPLUS_CLS *cls = cp->cls; CPLUS_CLS *sel = NULL; cp->ptalloc++; /* Ajoute un séparateur à la dernière déclaration */ for (i=0; inbcls; i++,cls++){ if (strcmp(cls->nom,nomcls)==0){ sel = cls; break; } } if (sel == NULL){ assert (i<1000); cp->nbcls++; sel = cls; cls->nom = cp->ptalloc; cls->nomf = ""; cp->ptalloc += strlen(nomcls)+1; strcpy (cls->nom,nomcls); } cp->cur = cp->decl + cp->nbdecl++; cp->cur->cls = sel; cp->cur->virtuel = 0; cp->cur->scope = 0; cp->cur->static_d = 0; cp->cur->text = cp->ptalloc; } static void near cplus_print (CPLUS *cp, const char *str) { cp->ptalloc = stpcpy (cp->ptalloc,str); } /* Compare deux prototypes, compare à partir du nom de la fonction seulement */ static int cmpdecl (const void *pt1, const void *pt2) { CPLUS_DECL *p1 = (CPLUS_DECL*)pt1; CPLUS_DECL *p2 = (CPLUS_DECL*)pt2; return strcmp (p1->nomfct,p2->nomfct); } /* Compare deux prototypes, compare à partir de la visibilite et du nom de la fonction seulement */ static int cmpdecl_scope (const void *pt1, const void *pt2) { CPLUS_DECL *p1 = (CPLUS_DECL*)pt1; CPLUS_DECL *p2 = (CPLUS_DECL*)pt2; int ret = p2->scope - p1->scope; if (ret == 0){ ret = strcmp (p1->nomfct,p2->nomfct); } return ret; } static bool sortscope = false; /* Enregistre le mode de tri des fonctions membres C++. Si sortscope est vrai, les fonctions sont classe par visibilite et ensuite pas ordre alphabetique. */ void cplus_setsort(bool _sortscope) { sortscope = _sortscope; } /* Tri toutes les déclarations */ static void near cplus_sort (CPLUS *cp) { hsort (cp->decl,cp->nbdecl,sizeof(CPLUS_DECL) ,sortscope ? cmpdecl_scope : cmpdecl); } static char *tbscope[]={ "private:\n", "protected:\n", "public:\n" }; /* Produit un fichier de déclaration par classe */ void cplus_makepp (CPLUS *cp, const char *ext, int verbose) { int i; CPLUS_CLS *cls = cp->cls; for (i=0; inbcls; i++,cls++){ char *buf = cp->ptalloc; cplus_setname (cp,cls->nom,ext,buf); cls->nomf = buf; cp->ptalloc += strlen(buf)+1; if (verbose == 2) printf ("\t-> %s\n",buf); { FILE *fout = fopen_err (buf,"w",1); int curscope = -1; int j; CPLUS_DECL *decl = cp->decl; for (j=0; jnbdecl; j++,decl++){ if (decl->cls == cls){ if (curscope != decl->scope){ curscope = decl->scope; fputs (tbscope[curscope],fout); } fputs ("\t",fout); if (decl->virtuel){ fputs("virtual ",fout); } if (decl->static_d){ fputs("static ",fout); } fputs(decl->text,fout); } } /* Assure que le header laisse un état stable */ if (curscope != 2) fputs ("public:\n",fout); fclose (fout); } } } /* Génère les prototypes associé à cette classe dans str Retourne -1 si erreur 0 si trouve pas de prototype pour nomcls 1 si ok */ int cplus_merge (CPLUS *cp, const char *nomcls, char *str) { int ret = -1; CPLUS_CLS *cls = cp->cls; int i; CPLUS_CLS *sel = NULL; str[0] = '\0'; for (i=0; inbcls; i++,cls++){ if (strcmp(cls->nom,nomcls)==0){ sel = cls; break; } } if (sel == NULL){ ret = 0; }else{ int j; int curscope = -1; CPLUS_DECL *decl = cp->decl; ret = 1; for (j=0; jnbdecl; j++,decl++){ if (decl->cls == sel){ if (curscope != decl->scope){ curscope = decl->scope; str = stpcpy (str,tbscope[curscope]); } *str++ = '\t'; if (decl->virtuel){ str = stpcpy (str,"virtual "); } if (decl->static_d){ str = stpcpy (str,"static "); } str = stpcpy (str,decl->text); } } if (curscope != 2) strcpy (str,"public:\n"); } return ret; } static char defcateg=0; /* Enregistre la catégorie à associer au fonctions membres qui n'en ont pas (private=0,protected=1,public=2) Initialement private. */ void cplus_setdefault (int def) { defcateg = def; } /* Traduit les mot PUBLIC PROTECTED et PRIVATE, ainsi que VIRTUAL Incrit private: si aucune des trois catégorie n'est encontrée */ static void near cplus_categ (CPLUS *cp, char *line) { int scope = defcateg; int virtuel = 0; int static_d = 0; char mot[50]; char *pt = mot; while (isalnum(*line) || *line == '_') *pt++ = *line++; *pt = '\0'; if (strcmp(mot,"PUBLIC")==0){ scope = 2; }else if (strcmp(mot,"PROTECTED")==0){ scope = 1; }else if (strcmp(mot,"PRIVATE")==0){ scope = 0; }else if (strcmp(mot,"VIRTUAL")==0){ virtuel = 1; }else if (strcmp(mot,"STATIC")==0){ static_d = 1; }else if (mot[0] != '\0'){ cplus_print (cp,mot); cplus_print (cp," "); } /* Saute les espace */ while (isspace(*line)) line++; /* Accumule le mot suivant */ pt = mot; while (isalnum(*line) || *line == '_') *pt++ = *line++; *pt = '\0'; if (strcmp(mot,"VIRTUAL")==0){ virtuel = 1; while (isspace(*line)) line++; }else if (strcmp(mot,"STATIC")==0){ static_d = 1; while (isspace(*line)) line++; }else{ cplus_print (cp,mot); } cplus_print (cp,line); cp->cur->virtuel = virtuel; cp->cur->scope = scope; cp->cur->static_d = static_d; } /* Décompose une fichier de prototype C++ en déclaration par classe La structure est initialisé et rempli. */ void cplus_parse (CPLUS *cp, const char *path) { FILE *fin = vfopen_err (path,"r",1); char line[300]; cplus_init (cp,(int)file_size(path)); while (fgets(line,sizeof(line)-1,fin)!=NULL){ if (line[0] != '/' && !isspace (line[0])){ char *pt = strchr (line,':'); if (pt == NULL){ fprintf (stderr,MSG_B(E_IVLDFILE ,"fichier %s invalide: décomposition annulé\n" ,"Invalid file %s: Can't be splitted\n"),path); exit (-1); }else{ /* #Spécification: fichier .pm / classe imbriquée proto supporte les classes imbriquée et distribura correctement les déclarations de type a::b::f() dans les blocs d'insertion de format ~PROTOBEG~ a::b */ char *nextpt = pt+2; while (*nextpt > ' '){ if (*nextpt == ':'){ pt = nextpt; nextpt++; } nextpt++; } char *nomfct = pt+2; *pt-- = '\0'; while (pt >= line && !isspace (*pt) && *pt != '*' && *pt != '&') pt--; pt++; cplus_select (cp,pt); *pt = '\0'; cplus_categ (cp,line); cp->cur->nomfct = cp->ptalloc; cplus_print (cp,nomfct); /* Génère les lignes de continuation Ajoute un tabulateur à ces ligne, elle sont déjà indenter, mais il faut deux indentations */ line[0] = '\t'; while (1){ /* Compatibilité fichier texte DOS UNIX */ nomfct = strip_end (nomfct); if (nomfct[-1] == ';'){ break; }else if(fgets(line+1,sizeof(line)-2,fin)==NULL){ break; }else{ cplus_print (cp,line); nomfct = line; } } } } } cp->ptalloc++; cplus_sort (cp); fclose (fin); }