/* * REFS.C * * Bringup a cross reference editor window. The file S:dme.refs and * dme.refs in the current directory are searched for the reference. * If found, the file specified is searched and the segment specified * loaded as a new file in a new window. */ #include "defs.h" #include Prototype void do_addpath (void); Prototype void do_rempath (void); Prototype void do_ctags (void); Prototype void do_refs (void); Prototype int searchref (char *, char *, char **, char **, int *, char **); Prototype int dirpart (char *); Prototype MLIST PBase; #define PEN struct _PEN PEN { MNODE Node; char *path; }; MLIST PBase; /* special DME paths */ /* * Special DME paths for REF and CTAGS */ #ifndef NO_DO2 void do_addpath() { PEN *pen; short len = strlen(av[1]); for (pen = (PEN *)PBase.mlh_Head; pen->Node.mln_Succ; pen = (PEN *)pen->Node.mln_Succ) { if (strcmp(av[1], pen->path) == 0) return; } if (pen = malloc(sizeof(PEN)+len+2)) { pen->path = (char *)(pen + 1); strcpy(pen->path, av[1]); switch(pen->path[len-1]) { case ':': case '/': break; default: strcat(pen->path, "/"); } } AddTail((LIST *)&PBase, (NODE *)pen); } void do_rempath() { PEN *pen, *npen; for (pen = (PEN *)PBase.mlh_Head; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { if (WildCmp(av[1], pen->path)) { Remove((NODE *)pen); free(pen); } } } #endif #ifndef NO_DO_CTAGS /* * Implement ctags */ void do_ctags() { char str[64]; char path[128]; char buf[128]; char sbuf[128]; short xlen; short slen; short dbaselen; BPTR oldlock = CurrentDir((BPTR)Ep->dirlock); ED *ed; { short i, j; for (i = Ep->Column; Current[i] == ' '; ++i); for (j = i; ; ++j) { short c = Current[j]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c >= '0' && c <= '9')) continue; break; } j -= i; if (j > 63) j = 63; movmem(Current+i, str, j); str[j] = 0; xlen = j; } if (!Ep->iconmode) title("search tags"); { FILE *fi; PEN *pen, *npen; long i; short j, len; dbaselen = dirpart(Ep->Name); movmem(Ep->Name, path, dbaselen); strcpy(path+dbaselen, "tags"); /* * Note: pen not used first pass and set to list head, so next * pass it will be the first element. * * Note2: The file path depends on several factors. (1) tags in * 'current' directory, use path to name of current window. * (2) tags in directory in DME special path, use special * path. (3) tag entry is a full path name, override * previous directories. */ for (pen = (PEN *)&PBase; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { mountrequest(0); if (fi = fopen(path, "r")) { mountrequest(1); while ((len = xefgets(fi, buf, 128)) >= 0) { for (j = 0; buf[j] && buf[j] != ' '; ++j); if (j == 0 || buf[0] == '#') continue; if (j == xlen && strncmp(str, buf, j) == 0) { while (buf[j] == ' ') ++j; /* * Extract the file name into str. If the * filename does not contain an absolute path, * prepend it with such. */ { char prep = 1; for (i = 0; buf[j] && buf[j] != ' '; ++i, ++j) { str[i] = buf[j]; if (str[i] == ':') prep = 0; } if (prep) { movmem(str, str + dbaselen, i); movmem(path, str, dbaselen); i += dbaselen; } } str[i] = 0; while (buf[j] && buf[j] != '^') /* SEARCH ARG */ ++j; fclose(fi); if (buf[j] != '^') { title("tags error"); goto done; } ++j; strcpy(sbuf, buf+j); slen = strlen(sbuf); if ((ed = finded(str, 0)) == NULL) { strcpy(buf, "newwindow newfile "); strcat(buf, str); do_command(buf); ed = finded(str, 0); } else { WindowToFront(ed->Win); ActivateWindow(ed->Win); } if (ed == NULL) { title("unable to load file"); goto done; } text_switch(ed->Win); if (Ep->iconmode) uniconify(); else text_cursor(0); for (i = 0; i < ed->Lines; ++i) { if (strncmp(ed->List[i], sbuf, slen) == 0) break; } sprintf(buf, "first goto %ld", i+1); do_command(buf); goto done; } } fclose(fi); } else { mountrequest(1); } if (npen->Node.mln_Succ) { strcpy(path, npen->path); strcat(path, "tags"); dbaselen = strlen(npen->path); } } title("tag not found"); } done: CurrentDir(oldlock); } #endif #ifndef NO_DO_REFS /* * Implement references */ void do_refs() { char str[256]; char path[128]; char *srch; char *file; char *estr; long len; int bcnt = 10; short i, j; short slen, elen; FILE *fi, *fj; short tmph, tmpw; BPTR oldlock = CurrentDir((BPTR)Ep->dirlock); for (i = Ep->Column; Current[i] == ' '; ++i); /* skip spaces */ { char c; for (j = 0; c = Current[i]; ++i, ++j) { str[j] = c; if (c >= 'a' && c <= 'z') continue; if (c >= 'A' && c <= 'Z') continue; if (c == '_') continue; break; } str[j] = 0; } title("search .refs"); { PEN *pen; PEN *npen; strcpy(path, "dme.refs"); /* warning, am assuming 8 char name */ mountrequest(0); for (pen = (PEN *)&PBase; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { if (searchref(path, str, &srch, &file, &len, &estr)) { mountrequest(1); goto found; } if (npen->Node.mln_Succ) { strcpy(path, npen->path); strcat(path, "dme.refs"); } } title("Reference not found"); mountrequest(1); goto done; } found: title("search file"); slen = strlen(srch); if (estr) elen = strlen(estr); fi = fopen(file, "r"); if (fi == NULL) { /* try using path prefix */ strcpy(str, path); strcpy(str + strlen(str) - 8, file); fi = fopen(str, "r"); } if (fi) { short lenstr; if (srch[0] == '@' && srch[1] == '@') { fseek(fi, atoi(srch+2), 0); if ((lenstr = xefgets(fi, str, 256)) >= 0) goto autoseek; } while ((lenstr = xefgets(fi, str, 256)) >= 0) { if (strncmp(str, srch, slen) == 0) { autoseek: title("load.."); if (fj = fopen("t:dme_ref", "w")) { tmph = 0; tmpw = 0; do { if (lenstr > tmpw) tmpw = strlen(str); ++tmph; fputs(str, fj); fputc('\n', fj); if (estr && strncmp(str,estr,elen) == 0) break; --len; } while ((lenstr=xefgets(fi, str, 256)) >= 0 && len); fclose(fj); if (tmph > 10) tmph = 10; if (tmpw > 80) tmpw = 80; sprintf(str, "openwindow +0+0+%d+%d newfile t:dme_ref", (tmpw<<3)+24, (tmph<<3)+24); do_command(str); unlink("t:dme_ref"); } else { title("Unable to open t:dme_ref for write"); } fclose(fi); free(srch); free(file); if (estr) free(estr); goto done; } if (--bcnt == 0) { /* check break every so so */ bcnt = 50; if (breakcheck()) break; } } fclose(fi); title("Search failed"); } else { title("Unable to open sub document"); } free(srch); free(file); if (estr) free(estr); done: CurrentDir(oldlock); } /* * Reference file format: * * `key' `lines' `file' `searchstring' * * where `lines' can be a string instead ... like a read-until, otherwise * the number of lines to read from the reference. */ searchref(file, find, psstr, pfile, plines, pestr) char *file, *find; char **psstr, **pfile, **pestr; long *plines; { FILE *fi; char buf[256]; char *ptr, *base; char *b1, *b2, *b3, *b4; char quoted; short findlen = strlen(find); if (fi = fopen(file, "r")) { while (xefgets(fi, (base=buf), 256) >= 0) { if (buf[0]=='#') continue; ptr = breakout(&base, "ed, &b1); /* if (ptr && *ptr && strncmp(ptr, find, findlen) == 0) { */ if (ptr && *ptr && strcmp(ptr, find) == 0) { if (ptr = breakout(&base, "ed, &b2)) { *pestr = NULL; *plines = atoi(ptr); if (*plines == 0) { *pestr = (char *)malloc(strlen(ptr)+1); strcpy(*pestr, ptr); } if (ptr = breakout(&base, "ed, &b3)) { *pfile = (char *)malloc(strlen(ptr)+1); strcpy(*pfile, ptr); if (ptr = breakout(&base, "ed, &b4)) { *psstr = (char *)malloc(strlen(ptr)+1); strcpy(*psstr, ptr); fclose(fi); if (b1) free(b1); if (b2) free(b2); if (b3) free(b3); if (b4) free(b4); return(1); } free(*pfile); if (b4) free(b4); } if (pestr) free (*pestr); if (b3) free (b3); } if (b2) free(b2); } if (b1) free(b1); } fclose(fi); } return(0); } #endif #ifndef NO_DO_CTAGS dirpart(str) char *str; { short i; for (i = strlen(str) - 1; i >= 0; --i) { if (str[i] == '/' || str[i] == ':') break; } return(i+1); } #endif