#include #include #include #include #define max_ranuras 10 /* numero de ranuras */ #define max_campos 24 /* maximo de campos por registro */ #define tam_buffer 10000 /* buffer de lineas */ #define tam_tib 200 /* buffer de entrada de ordenes */ #define max_tok 20 /* palabras en la linea de ordenes */ struct nodo{ struct nodo *ant; struct nodo *sig; char *registro; char *campos[max_campos]; unsigned int banderas; }; struct ranura{ struct nodo *P; /* puntero a primer elemento */ struct nodo *A; /* puntero a elemento actual */ struct nodo *U; /* puntero a ultimo elemento */ struct nodo **indices[max_campos]; char *etiqueta; }puerto[max_ranuras]; char buffer[tam_buffer]; char tib[tam_tib]; char *pc[max_tok]; FILE *COMMAND; /* entrada de ordenes de archivo */ char flag_terminal=1; /* entrada por defecto de terminal */ char salir=0; /* flag para terminar el programa */ int SLOT; /* ranura actual */ int TOK; /* token actual */ char *mensajes[]={ /* 0*/ "slot expected", /* 1*/ "slot out of range", /* 2*/ "non empty slot", /* 3*/ "empty slot", /* 4*/ "file expected", /* 5*/ "open w failed", /* 6*/ "open r failed", /* 7*/ "fields to browse?", /* 8*/ "field expected", /* 9*/ "field does not exists", /* 10*/ "mask expected", /* 11*/ "bit expected", /* 12*/ "bit out of range", /* 13*/ "logic operator expected", /* 14*/ "value expected", /* 15*/ "not a logic operator", /* 16*/ "cat not possible: incompatible tables" }; /*============================================================================== ESTA SECCION CONTIENE LAS FUNCIONES QUE MANIPULAN LAS ESTRUCTURAS DE DATOS. ==============================================================================*/ /*-----------------------------------------*/ int atoint(char *cadena) { int valor=0; char *p=cadena; while (*p!='\0') { valor=10*valor+(int)((*p)-48); ++p; } return(valor); } /*-----------------------------------------*/ void iniciar_puerto(int j) { int k; puerto[j].P=puerto[j].A=puerto[j].U=NULL; for(k=0;kant=NULL; q->sig=NULL; puerto[ranura].P=q; puerto[ranura].A=q; puerto[ranura].U=q; } else { q->ant=puerto[ranura].U; q->sig=NULL; puerto[ranura].U->sig=q; puerto[ranura].U=q; } q->registro=(char *)malloc(strlen(buffer)+1); strcpy(q->registro,buffer); dividir_registro(q->registro,q->campos); q->banderas=0; } for(j=0;jsig!=NULL) { q=q->sig; free(q->ant->registro); free(q->ant); } free(q->registro); free(q); for(j=0;jsig; while (p!=NULL) { ++contador; p=p->sig; } return(contador); } /*----------------------------------------- el argumento 'modo' indica si la comparacion se hara alfabetica mediante strcmp o numerica, despues de haber convertido la cadena a numero mediante atoint(); 0 alfabetica; 1 numerica -------------------------------------------*/ void ordenar_indice(int ranura, int campo, int A, int Z, int modo) { int i=A,j=Z; struct nodo **s=puerto[ranura].indices[campo]; struct nodo *temp; char *pivot=(*(s+(A+Z)/2))->campos[campo]; int pivottoint; while (i<=j){ if (modo==0) { while (strcmp((*(s+i))->campos[campo],pivot)<0) ++i; while (strcmp((*(s+j))->campos[campo],pivot)>0) --j; } else { pivottoint=atoint(pivot); while (atoint((*(s+i))->campos[campo])campos[campo])>pivottoint) --j; } if (i<=j) { temp=*(s+i); *(s+i)=*(s+j); *(s+j)=temp; ++i; --j; } } if (j>A) ordenar_indice(ranura,campo,A,j,modo); if (isig; int j, n=contar_registros(ranura); struct nodo **q; puerto[ranura].indices[campo]=(struct nodo **)malloc(n*sizeof(struct nodo *)); q=puerto[ranura].indices[campo]; for(j=0;jsig; } ordenar_indice(ranura,campo,0,n-1,modo); return; } /*-----------------------------------------*/ int buscar(int ranura, int campo, char *valor) { struct nodo *p=puerto[ranura].P->sig; while (p!=NULL){ if (!strcmp(p->campos[campo],valor)){ puerto[ranura].A=p; return(0); } p=p->sig; } return(-1); } /*-----------------------------------------*/ void prn0(struct nodo *p) { int j=0; printf("\n"); while (p->campos[j]!=NULL){ printf("%s\n",p->campos[j]); ++j; } return; } /*-----------------------------------------*/ int n_campo(int ranura, char *valor) { int j=0; struct nodo *p=puerto[ranura].P; while (p->campos[j]!=NULL) { if (!strcmp(p->campos[j],valor)) return(j); ++j; } return(-1); } /*============================================================================== ESTA SECCION CONTIENE LAS FUNCIONES PARA PRESENTAR LA INTERFAZ E INTERPRETAR LAS ORDENES. ==============================================================================*/ /*-----------------------------------------*/ void error(char *mensaje) { printf("\nOops!: %s\n\n",mensaje); return; } /*-----------------------------------------*/ void nerror(int n) { printf("\nOops!: %s\n\n",mensajes[n]); return; } /*-----------------------------------------*/ void presentacion() { printf("\n"); printf(" ### \n"); printf(" ## \n"); printf(" ## \n"); printf(" ##### \n"); printf(" ## ##\n"); printf(" ## ##\n"); printf(" ## ##\n"); printf(" ## ###### \n"); printf(" # \n"); printf(" # \n"); printf("\n"); return; } /*-----------------------------------------*/ void nocr(char *cadena) { char *p=cadena; while (*p!='\n'){ if (*p=='\0') return; ++p; } *p='\0'; return; } /*-----------------------------------------*/ void divide(char *cadena, char *indices[], int n) { /* presupone la eliminación del \n */ char *p=cadena; int j; for(j=0;j=")) return(1); if (!strcmp(cadena,">")) return(1); if (!strcmp(cadena,"<>")) return(1); return(0); } /*----------------------------------------- comprueba los argumentos. Toma una cadena que indica cuantos y de que tipo son los argumentos que se esperan a continuacion de TOK; estos argumentos se especifican de la siguiente forma: r -> slot; + se espera lleno, - se espera vacio a -> archivo; + para escribir; - para leer c -> un campo, va seguido de un digito que indica el argumento (contado desde 1) donde se dice la ranura donde esta la tabla a la que pertenece el campo m -> mascara b -> un valor numerico que representa un bit $ -> una cadena o -> operador Se devuelve -1 si todo OK. Si hay algun error, se devuelve el numero del mensaje. Presupone que la cadena de argumentos no contiene error, asi que no devuelve error interno -----------------------------------------*/ int comprueba_argumentos(char *formato) { char *c=formato; int n; int narg=1; FILE *f; while (*c!='\0') { if (*c=='r') /* ranura */ { if (pc[TOK+narg]==NULL) return(0); n=atoint(pc[TOK+narg]); if ((n<0)||(n>max_ranuras-1)) return(1); if (*(c+1)=='+') { if (puerto[n].P==NULL) return(3); } else { if (puerto[n].P!=NULL) return(2); } c+=2; ++narg; } else if (*c=='a') /* archivo */ { if (pc[TOK+narg]==NULL) return(4); if (*(c+1)=='+') { if ((f=fopen(pc[TOK+narg],"w"))==NULL) return(5); } else { if ((f=fopen(pc[TOK+narg],"r"))==NULL) return(6); } fclose(f); c+=2; ++narg; } else if (*c=='c') { if (pc[TOK+narg]==NULL) return(8); n=(int)(*(c+1))-48; if (n_campo(atoint(pc[TOK+n]),pc[TOK+narg])==-1) return(9); c+=2; ++narg; } else if (*c=='m') { if (pc[TOK+narg]==NULL) return(10); c+=1; ++narg; } else if (*c=='b') { if (pc[TOK+narg]==NULL) return(11); n=atoint(pc[TOK+narg]); if ((n<0)||(n>31)) return(12); c+=1; ++narg; } else if (*c=='v') { if (pc[TOK+narg]==NULL) return(14); c+=1; ++narg; } else if (*c=='o') { if (pc[TOK+narg]==NULL) return(13); if (!es_operador_logico(pc[TOK+narg])) return(15); c+=1; ++narg; } } return(-1); /* OK */ } /*----------------------------------------- escribe un registro en un archivo -----------------------------------------*/ void escribe_registro(struct nodo *p, FILE *f) { int j=0; while (p->campos[j]!=NULL) { fprintf(f,p->campos[j]); if (p->campos[j+1]==NULL) fprintf(f,"\n"); else fprintf(f,","); ++j; } return; } /*----------------------------------------- escribe los campos especificados por la mascara -----------------------------------------*/ void escribe_registro_enmascarado(struct nodo *p, FILE *f, char *mascara) { char *c=mascara; int j=0; char flag=0; j=0; flag=0; while (*(c+j)!='\0') { if (p->campos[j]==NULL) break; if (*(c+j)!='-') { if (flag==0) { flag=1; fprintf(f,p->campos[j]); } else { fprintf(f,","); fprintf(f,p->campos[j]); } } ++j; } fprintf(f,"\n"); return; } /*----------------------------------------- presenta las ranuras slots -----------------------------------------*/ int slots() { int j; printf("\n"); for(j=0;j -----------------------------------------*/ int load() { int n; char formato[]="r-a-"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } /* if (cargar(atoint(pc[TOK+1]),pc[TOK+2])==1) { nerror(6); return(1); } */ cargar(atoint(pc[TOK+1]),pc[TOK+2]); TOK+=2; return(0); } /*----------------------------------------- descarga unload -----------------------------------------*/ int unload() { int n; char formato[]="r+"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } descargar(atoint(pc[TOK+1])); TOK+=1; return(0); } /*----------------------------------------- numero de registros nregs -----------------------------------------*/ int nregs() { int n; char formato[]="r+"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } printf("\n%d\n\n",contar_registros(atoint(pc[TOK+1]))); ++TOK; return(0); } /*----------------------------------------- enseña los campos de una ranura fields -----------------------------------------*/ int fields() { int n,ranura,j; char formato[]="r+"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } j=0; ranura=atoint(pc[TOK+1]); printf("\n"); while (puerto[ranura].P->campos[j]!=NULL) { printf("%s\n",puerto[ranura].P->campos[j]); ++j; } printf("\n"); ++TOK; return(0); } /*----------------------------------------- salva a un archivo temporal los campos especificados por la mascara -----------------------------------------*/ int cortar(int ranura, char *mascara) { int j; char flag; char *c=mascara; struct nodo *q=puerto[ranura].P; FILE *f; if ((f=fopen("temporalb","w"))==NULL) return(1); while (q!=NULL) { escribe_registro_enmascarado(q,f,mascara); q=q->sig; } fclose(f); return(0); } /*----------------------------------------- enseña mediante 'less' los campos que se especifiquen mediante la mascara browse |all -----------------------------------------*/ int browse() { char *c; struct nodo *q; int ranura,j,n; FILE *f; char formato[]="r+m"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); if (!strcmp(pc[TOK+2],"all")) { /* todos los campos */ if ((f=fopen("temporalb","w"))==NULL) return(1); q=puerto[ranura].P; while (q!=NULL) { escribe_registro(q,f); q=q->sig; } fclose(f); TOK+=2; system("cat temporalb | less"); return(0); } else { if (cortar(ranura,pc[TOK+2])==1) { return(1); } else { TOK+=2; system("cat temporalb | less"); return(0); } } } /*------------------------------------------- enseña la base de datos, pero ordenada por el campo que se especifique; con 'all' todos los campos y con una mascara solo los que se especifiquen browseby all| -------------------------------------------*/ int browseby(int modo) { char *c; struct nodo *q; int ranura,campo,n,j; FILE *f; char formato[]="r+c1m"; if ((f=fopen("temporalb","w"))==NULL) { nerror(5); return(1); } if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); campo=n_campo(ranura,pc[TOK+2]); /* indexar */ if (puerto[ranura].indices[campo]!=NULL) free(puerto[ranura].indices[campo]); indexar_campo(ranura,campo,modo); if (!strcmp(pc[TOK+3],"all")) { /* todos los campos */ q=puerto[ranura].P; escribe_registro(q,f); n=contar_registros(ranura); for(j=0;j -------------------------------------------*/ int cut() { char *c; struct nodo *q; int ranura,j,n; FILE *f; char temp[100]; char formato[]="r+r-m"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } if (cortar(atoint(pc[TOK+1]),pc[TOK+3])==1) { return(1); } else { if (cargar(atoint(pc[TOK+2]),"temporalb")==1) { return(1); } else { /* re-etiquetar */ strcpy(temp,"cut "); strcat(temp,pc[TOK+1]); strcat(temp," "); strcat(temp,pc[TOK+2]); strcat(temp," "); strcat(temp,pc[TOK+3]); etiquetar(atoint(pc[TOK+2]),temp); TOK+=3; return(0); } } } /*------------------------------------------- corta unos campos especificados de una ranura y los traspasa a otra ranura, pero ordenados por el campo que se especifique cutby -------------------------------------------*/ int cutby(int modo) { char *c; struct nodo *q; int ranura,campo,j,n; FILE *f; char temp[100]; char formato[]="r+r-c1m"; if ((f=fopen("temporalb","w"))==NULL) { nerror(5); return(1); } if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); campo=n_campo(ranura,pc[TOK+3]); /* indexar */ if (puerto[ranura].indices[campo]!=NULL) free(puerto[ranura].indices[campo]); indexar_campo(ranura,campo,modo); /* escribir cabecera y registros */ escribe_registro_enmascarado(puerto[ranura].P,f,pc[TOK+4]); n=contar_registros(ranura); for(j=0;j Pone a 0 las banderas de todos los registros -------------------------------------------*/ int unmark() { int ranura,n; struct nodo *p; char formato[]="r+"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); p=puerto[ranura].P->sig; while (p!=NULL) { p->banderas=0; p=p->sig; } return(0); } /*------------------------------------------- bitmark Activa el bit correspondiente cuando el campo especificado satisface la condicion -------------------------------------------*/ int bitmark(int modo) { int ranura,b,c,op,n; struct nodo *p; char formato[]="r+bc1ov"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); c=n_campo(ranura,pc[TOK+3]); b=atoint(pc[TOK+2]); if (!strcmp(pc[TOK+4],"<")) { op=0; } else if (!strcmp(pc[TOK+4],"<=")) { op=1; } else if (!strcmp(pc[TOK+4],"=")) { op=2; } else if (!strcmp(pc[TOK+4],">=")) { op=3; } else if (!strcmp(pc[TOK+4],">")) { op=4; } else if (!strcmp(pc[TOK+4],"<>")) { op=5; } /* cabecera */ p=puerto[ranura].P->sig; while (p!=NULL) { if (op==5) { if (modo==0) { if (strcmp(p->campos[c],pc[TOK+5])!=0) /* <> */ { p->banderas|=(1<campos[c])!=atoint(pc[TOK+5])) { p->banderas|=(1<campos[c],pc[TOK+5])==-1) /* < */ { p->banderas|=(1<campos[c])banderas|=(1<campos[c],pc[TOK+5])<=0) /* <= */ { p->banderas|=(1<campos[c])<=atoint(pc[TOK+5])) { p->banderas|=(1<campos[c],pc[TOK+5])==0) /* = */ { p->banderas|=(1<campos[c])==atoint(pc[TOK+5])) { p->banderas|=(1<campos[c],pc[TOK+5])>=0) /* >= */ { p->banderas|=(1<campos[c])>=atoint(pc[TOK+5])) { p->banderas|=(1<campos[c],pc[TOK+5])>0) /* > */ { p->banderas|=(1<campos[c])>=atoint(pc[TOK+5])) { p->banderas|=(1<sig; } TOK+=5; return(0); } /*------------------------------------------- selectmark selecciona los registros cuya bandera vale -------------------------------------------*/ int selectmark() { struct nodo *q; int n; FILE *f; char temp[100]; char formato[]="r+r-v"; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } /* seleccion */ if ((f=fopen("temporalb","w"))==NULL) { nerror(5); return(1); } q=puerto[atoint(pc[TOK+1])].P; escribe_registro(q,f); q=q->sig; while (q!=NULL) { if (q->banderas==atoint(pc[TOK+3])) { escribe_registro(q,f); } q=q->sig; } fclose(f); if (cargar(atoint(pc[TOK+2]),"temporalb")==1) { return(1); } else { /* re-etiquetar */ strcpy(temp,"selectmark "); strcat(temp,pc[TOK+1]); strcat(temp," "); strcat(temp,pc[TOK+2]); strcat(temp," "); strcat(temp,pc[TOK+3]); etiquetar(atoint(pc[TOK+2]),temp); TOK+=3; return(0); } } /*------------------------------------------- html toma como origen una ranura y como destino un nombre de archivo, y genera una tabla html a partir de los datos de la tabla que se encuentra en . Las columnas se alinean según diga la cadena de formato, que es una secuencia de l,r,c (izquierda, derecha,centro) -------------------------------------------*/ int html() { struct nodo *q; int j,n,ranura; FILE *f; char formato[]="r+a+m"; char flag=0; char *c; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } ranura=atoint(pc[TOK+1]); q=puerto[ranura].P; f=fopen(pc[TOK+2],"w"); fprintf(f,"\n"); while (q!=NULL) { if (flag==0) { fprintf(f,"\n"); flag=1; } else { fprintf(f,"\n"); flag=0; } j=0; c=pc[TOK+3]; while (q->campos[j]!=NULL) { if ((*c=='r')&&(*c!='\0')) { fprintf(f,"",q->campos[j]); } else if ((*c=='c')&&(*c!='\0')) { fprintf(f,"",q->campos[j]); } else { fprintf(f,"",q->campos[j]); } ++j; ++c; } fprintf(f,"\n\n"); q=q->sig; } fprintf(f,"
%s%s%s
"); fclose(f); TOK+=3; return(0); } /*------------------------------------------ merge -------------------------------------------*/ int cat() { struct nodo *p,*q; char formato[]="r+r+"; int n; int a=atoint(pc[TOK+1]); int b=atoint(pc[TOK+2]); if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } /* comprobar que las tablas tienen el mismo formato; si no, dar error */ if (strcmp(puerto[a].P->registro,puerto[b].P->registro)) { nerror(16); return(1); } puerto[a].U->sig=puerto[b].P->sig; puerto[b].P->sig->ant=puerto[a].U; puerto[a].U=puerto[b].U; free(puerto[b].P->registro); free(puerto[b].P); iniciar_puerto(b); return(0); } /*------------------------------------------- cambia la entrada de terminal a archivo run -------------------------------------------*/ int run() { char formato[]="a-"; int n; if ((n=comprueba_argumentos(formato))!=-1) { nerror(n); return(1); } COMMAND=fopen(pc[TOK+1],"r"); flag_terminal=0; return(0); } /*-----------------------------------------*/ int procesar_palabra() { if (!strcmp(pc[TOK],"quit")) { salir=1; } else if (!strcmp(pc[TOK],"slots")) { return(slots()); } else if (!strcmp(pc[TOK],"load")) { return(load()); } else if (!strcmp(pc[TOK],"unload")) { return(unload()); } else if (!strcmp(pc[TOK],"nregs")) { return(nregs()); } else if (!strcmp(pc[TOK],"fields")) { return(fields()); } else if (!strcmp(pc[TOK],"browse")) { return(browse()); } else if (!strcmp(pc[TOK],"browseby")) { return(browseby(0)); } else if (!strcmp(pc[TOK],"browseby-n")) { return(browseby(1)); } else if (!strcmp(pc[TOK],"cut")) { return(cut()); } else if (!strcmp(pc[TOK],"cutby")) { return(cutby(0)); } else if (!strcmp(pc[TOK],"cutby-n")) { return(cutby(1)); } else if (!strcmp(pc[TOK],"unmark")) { return(unmark()); } else if (!strcmp(pc[TOK],"bitmark")) { return(bitmark(0)); } else if (!strcmp(pc[TOK],"bitmark-n")) { return(bitmark(1)); } else if (!strcmp(pc[TOK],"selectmark")) { return(selectmark()); } else if (!strcmp(pc[TOK],"html")) { return(html()); } else if (!strcmp(pc[TOK],"cat")) { return(cat()); } else if (!strcmp(pc[TOK],"run")) { return(run()); } { } } /*-----------------------------------------*/ void procesar_linea() { int j; TOK=0; nocr(tib); divide(tib,pc,max_tok); /*debug j=0; while (pc[j]!=NULL) {printf("%s\n",pc[j]); ++j;}*/ while ((pc[TOK]!=NULL)&&(!salir)) { if (!procesar_palabra()) { ++TOK; } else { break; } } return; } /*-----------------------------------------*/ void leer_linea() { if (flag_terminal) { fgets(tib,tam_tib,stdin); } else { if (fgets(tib,tam_tib,COMMAND)==NULL) { /*printf("Batch terminated\n");*/ fclose(COMMAND); flag_terminal=1; } } } /*-----------------------------------------*/ main() { int n,j; iniciar_puertos(); presentacion(); while (!salir) { printf("> "); leer_linea(); procesar_linea(); } return; }