/* xbcmds.c is a module that combines the modules xbase.c and xbindex.c xbindex is a proprietary index system, while dbase.c should work with any xbase file system */ #include #include #include #include #include #include #include "xbindex.h" #include "xbase.h" #include "xbcmds.h" #if MSDOS #include #endif /* index info for global purposes */ /* xbase global variables */ extern select_rec *s[max_area]; extern long rec_num ; extern char area; extern int GRERROR ; extern int DOSERROR ; extern char IBMPC; extern int rr ; /* records_read */ extern char *filemode ; /* filemode */ /* field types */ extern char *character; extern char date[date_size] ; extern char numeric[19]; extern char *memo; extern FILE *tofile ; extern int scr_limit ; extern long result ; extern unsigned long memory; extern order_array_type temporder ; /* index & dummy info */ extern IX_DESC *pci; extern BLOCK spare_block; #define KEY_SIZE 20 int ndum = KEY_SIZE + sizeof(NULLREC); int fs = 20480; ENTRY dume= { NULLREC, { 0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xf0 } }; int compf(ENTRY *p1, ENTRY *p2) { return(strcmp((char *)&p1->key,(char *)&p2->key)); } int sizef(ENTRY *p1) { return(strlen(p1->key) + 1 + sizeof(RECPOS)); } /* end of dummy vars */ char *dxfile; FILE *idx_file; char *xfile; char found; int keylen; char *keystr; rel r[max_area][max_index]; char deleted = TRUE ; /* set delete status TRUE or FALSE */ /* begin xbase command functions */ void initcmds() { int i,j; for (i=1;iord) /* skip if this is the current order */ { if (s[a]->i[i].idx) /* check if index open */ { field_no = s[a]->i[i].pix->dx.order; strcpy((char *)s[a]->i[i].pe->key, s[a]->fd[field_no]); /* copy field info and record pointer */ s[a]->i[i].pe->rptr = s[a]->i[s[a]->ord].pe->rptr; } } } } void relation(char a, char o) { int i,j; char save_area,save_order; save_area = a; save_order = o; for (i=a;iord = r[i][j].c.i; rtrim(s[i]->i[j].pe->key); strcpy((char *)SI.pe->key,s[i]->i[j].pe->key); rec_num = find_key(SI.pe,SI.pix); if (rec_num != 0) { goto_rec(rec_num); other_rel(area); } } area = save_area; SA->ord = save_order; } void relationtemp(char a,char o) { char savarea,savorder; if (!SI.idx) return; savarea = a; savorder = o; setrelationships(a,o); area = savarea; SA->ord = savorder; } void setrelationships(char a,char o) { int ret; if (r[a][o].c.a == 0) return; /* done */ /* activate parent area */ area = r[a][o].c.a; SA->ord = r[a][o].c.i; /* copy child key to parent key */ strcpy((char *)SI.pe->key,(char *)s[a]->i[o].pe->key); ret = find_key(SI.pe,SI.pix); if (ret) { goto_rec(SI.pe->rptr); setrelationships(area,SA->ord); } } int open_index(char *fn,int dupok) { int dupixok; dupixok = dupok; SI.idx = TRUE; SI.pix = (IX_DESC *)calloc(1,sizeof(IX_DESC)); memchk((char *)SI.pix,"open_index","SI.pix",sizeof(IX_DESC)); SI.pe = (ENTRY *)calloc(1,sizeof(ENTRY)); memchk((char *)SI.pe,"open_index","SI.pe",sizeof(ENTRY)); if (openix(fn,SI.pix,compf,sizef)<0) { SI.idx = FALSE; free(SI.pix); free(SI.pe); return(0); } else { rtrim(SA->fd[SA->ord]); strcpy(SI.pe->key,SA->fd[SA->ord]); SI.pe->rptr = SA->crn; find_key(SI.pe,SI.pix); } return(1); } int close_index(IX_DESC *pix) { int ret; ret = close_if(pix->ixfile); if (ret) { SI.idx = FALSE; free((void *)SI.pix); free((void *)SI.pe); } return(ret); } void build_index(string xfile, int order) { int i,ret; if ((order < 0) || (order > SA->num_of_fields)) return; if (!make_index(xfile,1,order)) { return; } else { if (SA->hr->num_of_recs < 1) return; goto_rec(1); /* this ignores any indexes open */ if (open_index(xfile,1)) { for (i=1;i<=SA->hr->num_of_recs;i++) { if (SA->del != is_deleted) { SI.pe->rptr = i; rtrim(SA->fd[order]); strcpy((char *)SI.pe->key,SA->fd[order]); ret = add_key(SI.pe,SI.pix); } if (i < SA->hr->num_of_recs) { read_rec(area); } } close_index(SI.pix); } } } void reindex(char *idxname) { char order; dxname(idxname); if (SI.idx) { order = SI.pix->dx.order; close_index(SI.pix); build_index(idxname,order); open_index(idxname,1); } } void select(char newarea) { area = newarea; } void order(char area, char neworder) { s[area]->ord = neworder; } void use(string pstr1, string pstr2, char indexed) { int checkbreak; pstr1 = dbname(pstr1); pstr2 = dxname(pstr2); close_area(area); if (strlen(pstr1) > 4) { /* SA not calloced unless file open sucessfully */ if (open_file(pstr1,area)) SI.idx = indexed; } else { return; } checkbreak = TRUE; if (GRERROR != 0) { return; } else { SA->fok = TRUE; read_header(area); read_fields(area); read_rec(area); SA->crn = 1; if (SI.idx) { if (!open_index(pstr2,1)) SI.idx = FALSE; } top(); } } void close_area(char area) { int i; if (SA->fok) { for (i=1;ii[i].idx) close_index(s[area]->i[i].pix); close_file(area); } } /* indexed function only */ int find(char *key) { int rec_num; if (!SI.idx) return(0); first_key(SI.pe,SI.pix); strcpy((char *)SI.pe->key,key); rec_num = find_key(SI.pe,SI.pix); if (rec_num != 0) { goto_rec(rec_num); relation(area,SA->ord); return(1); } return(0); } int top() { long offset; long rec_num; if (SA->fok) { if (SI.idx) { rec_num = first_key(SI.pe,SI.pix); goto_rec(rec_num); } else { offset = (long)SA->hr->data_start; fseek(SA->fp,offset,0); read_rec(area); SA->crn = 1; } } else { return(0); } relation(area,SA->ord); return(1); } int bottom() { long offset; long rec_num; if (SA->fok) { if (SI.idx) { last_key(SI.pe,SI.pix); rec_num = prev_key(SI.pe,SI.pix); goto_rec(rec_num); } else { offset = (long)SA->hr->data_start+((SA->hr->num_of_recs-1) *SA->hr->cpr); fseek(SA->fp,offset,0); read_rec(area); SA->crn = (short)SA->hr->num_of_recs; } } else { return(0); } relation(area,SA->ord); return(1); } int skip(int skipped) { long offset; int stat; stat = 0; if (SA->fok) { if (SI.idx) { if (skipped == 1) { stat = next_key(SI.pe,SI.pix); if (stat != EOIX) { goto_rec(SI.pe->rptr); SA->crn = SI.pe->rptr; } } else { if (skipped == -1) { stat = prev_key(SI.pe,SI.pix); goto_rec(SI.pe->rptr); SA->crn = SI.pe->rptr; } } } if (!SI.idx) { if ((SA->crn + skipped) > SA->hr->num_of_recs) { stat = bottom(); } else { if ((SA->crn + skipped) < 1) { stat = top(); } else { offset = (long)SA->hr->data_start+ ((SA->crn+(skipped-1))*SA->hr->cpr); SA->crn = SA->crn + skipped; fseek(SA->fp,offset,0); stat = read_rec(area); } } } } relation(area,SA->ord); return(stat); } int match(string fld_str) { /* returns the index position of a fieldname */ int i; for(i=1;i<=SA->num_of_fields;i++) { if (strnicmps(SA->fr[i]->field_name,fld_str)==0) return(i); } return(0); } /* non-indexed only */ void locate(string field, string fld_data) { int i; if (SI.idx) return; top(); i = match(field); while((strnicmps(SA->fd[i],fld_data)!=0) && (!feof(SA->fp))) skip(1); return; } int edit_field_old(char *fld_str,char *newstr) { /* If the field the file is indexed on is changed then the index needs to be updated too. */ char field_no,save_order; if (!SA->fok) return(0); field_no = match((string)fld_str); if (field_no) { save_order = SA->ord; order(area,field_no); if ((SI.idx) && (field_no == SI.pix->dx.order)) { rtrim(SA->fd[field_no]); SI.pe->rptr = SA->crn; strcpy((char *)SI.pe->key,SA->fd[field_no]); if (!delete_key(SI.pe,SI.pix)) { order(area,(char)save_order); return(0); } } strcpy((char *)SA->fd[field_no],(char *)newstr); if ((SI.idx) && (field_no == SI.pix->dx.order)) { SI.pe->rptr = SA->crn; rtrim(SA->fd[field_no]); strcpy((char *)SI.pe->key,SA->fd[field_no]); if (!add_key(SI.pe,SI.pix)) { order(area,save_order); return(0); } } } else return(0); order(area,save_order); return(1); } int edit_field(char *fld_str,char *newstr) { char field_no; field_no = match((string)fld_str); if (field_no) { strcpy((char *)SA->fd[field_no],(char *)newstr); return(1); } else return(0); } int update_index(char *oldkey,char *newkey,char ord) { char old[MAXKEY]; char new[MAXKEY]; strcpy((char *)&old,oldkey); strcpy((char *)&new,newkey); /* insert the new key */ if (s[area]->i[ord].idx) { s[area]->i[ord].pe->rptr = SA->crn; strcpy((char *)s[area]->i[ord].pe->key,new); rtrim(s[area]->i[ord].pe->key); if (!add_key(s[area]->i[ord].pe,s[area]->i[ord].pix)) { return(0); } } else return(0); /* delete the old key */ if (s[area]->i[ord].idx) { s[area]->i[ord].pe->rptr = SA->crn; strcpy((char *)s[area]->i[ord].pe->key,old); rtrim(s[area]->i[ord].pe->key); if (!delete_key(s[area]->i[ord].pe,s[area]->i[ord].pix)) { return(0); } } else return(0); return(1); } int save_rec(char area) { char i; if (!SA->fok) return(0); else write_rec(area); for (i=1;ii[i].idx) if (strnicmps(SA->fd[s[area]->i[i].pix->dx.order], s[area]->i[i].pe->key)!=0) if (update_index(s[area]->i[i].pe->key, SA->fd[s[area]->i[i].pix->dx.order],i)) return(1); else return(0); return(1); } int append_blank(char area) { int i; if (add_rec(area)) { /* go to the appended record */ s[area]->crn = (short)s[area]->hr->num_of_recs; goto_rec(s[area]->hr->num_of_recs); } else return(0); /* if the file is indexed we need to add the keys */ for (i=1;ii[i].idx) /* if this index area is used */ { strcpy((char *)s[area]->i[i].pe->key, SA->fd[s[area]->i[i].pix->dx.order]); rtrim(s[area]->i[i].pe->key); s[area]->i[i].pe->rptr = SA->crn; add_key(s[area]->i[i].pe,s[area]->i[i].pix); /* add error routine */ } return(1); } char delete_rec(char area) { int i; if (!SA->fok) return(FALSE); else del_rec(area); for (i=1;ii[i].idx) delete_key(s[area]->i[i].pe,s[area]->i[i].pix); } /* void copy_for(var ok : boolean; var records_copied : int; field_num : int) { i : int; temp : string; operator : char; { ok = FALSE; temp = trim(field_data[field_num]); operator = cp[6][1]; case operator of '=' : if cp[6][2] = '=' { if temp = cp[7] ok = TRUE; } else if upstr(temp) = upstr(cp[7]) ok = TRUE; '#' : if upstr(temp) <> upstr(cp[7]) ok = TRUE; '<' : if cp[6][2] = '=' { if upstr(temp) <= upstr(cp[7]) ok = TRUE } else if upstr(temp) < upstr(cp[7]) ok = TRUE; '>' : if cp[6][2] = '=' { if upstr(temp) >= upstr(cp[7]) ok = TRUE } else if upstr(temp) > upstr(cp[7]) ok = TRUE; 'D' : if delete_flag <> 'D' ok = TRUE; else printf('invalid operator') }; if ok inc(records_copied); }; */ void copyfile(char *cp[]) { long i; char ok; char header_terminator; int num_of_fields; /* for local use only */ long num_of_recs; field_rec field; char eof_marker; int records_copied; int field_num; string tmpname; records_copied = 0; ok = TRUE; if (strnicmps(cp[2],"TO")==0) { /* from file would be SA->fp */ cp[3] = dbname(cp[3]); /* to file */ tmpname = cp[3]; /* select 0 is reserved for temporary files */ if ((s[0]->fp=fopen(cp[3],"wb+"))==NULL) /* create "to" file */ exit(0); fseek(SA->fp,0,0); /* reset ptr to beg of infile */ read_header(area); /* copy header to new file */ num_of_recs = SA->hr->num_of_recs; rr = fwrite((char *)SA->hr,sizeof(header_rec),1,s[0]->fp); /* copy field information, then add terminator byte */ num_of_fields = SA->num_of_fields; for (i=1;i<=num_of_fields;i++) { rr = fread((char *)&field,sizeof(field_rec),1,SA->fp); rr = fwrite((char *)&field,sizeof(field_rec),1,s[0]->fp); } rr = fread(&header_terminator,1,1,SA->fp); rr = fwrite(&header_terminator,1,1,s[0]->fp); /* now we decide which records to copy */ if (strnicmps(cp[5]," ")==0) field_num = 1; else field_num = match(cp[5]); /*field name*/ for (i=1;i<=SA->hr->num_of_recs;i++) { if ((strnicmps(cp[4],"FOR")!=0) && (strnicmps(cp[4],"WHILE")!=0)) rr = fread(SA->rd,SA->hr->cpr,1,SA->fp); else { read_rec(area); /* copy_for(ok,records_copied,field_num); */ } if (ok) rr = fwrite(SA->rd,(SA->hr->cpr),1,s[0]->fp); } rr = fread(&eof_marker,1,1,SA->fp); rr = fwrite(&eof_marker,1,1,s[0]->fp); /* adjust the SA->hr of the to file */ if ((strnicmps(cp[4],"FOR")==0) || (strnicmps(cp[4],"WHILE")==0)) { fseek(s[0]->fp,0,0); SA->hr->num_of_recs = records_copied; rr = fwrite((char *)&SA->hr,sizeof(header_rec),1,s[0]->fp); } SA->hr->num_of_recs = num_of_recs; /*restore infile rec count*/ close_file(0); } }