/****************************************************************************** Author: Brad Long Version 1.0 (1992) Version 3.0 (5 Dec 1994) Version 4.0 (27 May 1998) Notes: 'inc' scans Progress files for included files and programs. To compile use 'cc' or 'gcc'. It should compile in DOS with a good compiler. Various options are allowed for different purposes as follows: Option Purpose ---------- ------------ -r Recursively searches the given file and all included files down to a recursion depth of MAXLVL. Infinite recursion is detected by keeping an internal list of programs recursed in the current strand and backed out, if necessary, to the previous recursion level. -p Progress programs that are 'run' from the given file are also scanned. -f Makes 'inc' output the contents of the given file and all those subsequently scanned. -h When used with '-f', does not output the header comments of subsequently scanned files. -l When used with '-f', outputs the file name with each line of output. -i list Ignores recursing programs in the comma separated list -s pathlist Searches for files along paths supplied in the comma separated list -u Within a call level, shows the called or included file once only (i.e. multiple calls are reported once) ******************************************************************************/ #include #include #include #include #include #include #define MAXLVL 100 #define MAXPATH 1024 struct stat buf; static int scan(); static char path[MAXPATH], iglist[MAXPATH], spath[MAXPATH], tpath[MAXPATH]; static int recurse, full, header, program, list, ignore, search, unique; main(argc, argv) int argc; char *argv[]; { int optok, i; optok = 1; for (i=1; i < argc; ++i) { if (!(**(++argv) == '-' && optok)) break; switch (*((*argv)+1)) { case 'u': unique = 1; break; case 'f': full = 1; break; case 'h': header = 1; break; case 'l': list = 1; break; case 'p': program = 1; break; case 'r': recurse = 1; break; case 's': search = 1; ++i; /* nasty */ if (i < argc) { strcpy(spath,","); strcat(spath,*++argv); strcat(spath,","); } break; case 'i': ignore = 1; ++i; /* nasty */ if (i < argc) { strcpy(iglist,","); strcat(iglist,*++argv); strcat(iglist,","); } break; default: optok = 0; } } if (i < argc && optok) for (; i < argc; ++argv, ++i) { printf("[scanning %s]\n",*argv); (void) scan(*argv, 0); } else { printf("usage: inc [-f] [-h] [-i list] [-l] [-p] [-r] [-s pathlist] [-u] file\nOptions:\n\n"); printf(" -f Full Listing\n"); printf(" -h Ignore header comments of include files (used with -f)\n"); printf(" -i list Ignore recursing files in the comma separated list\n"); printf(" -l Print file name on every line (used with -f)\n"); printf(" -p Also show programs (.p files)\n"); printf(" -r Expand (recurse) all include files\n"); printf(" -s pathlist Searches for files along the comma separated list of paths\n"); printf(" -u Don't show multiple calls within the same file\n"); } } static int scan (fname, level) char *fname; int level; { char word[50], zfname[50], tname[100], uqlist[MAXPATH]; int i, n, star, slash, comment, sqt, dqt, ch, brace, w, skiph, gotword, r, ru, run, prun, lastch, dot, lastout, ok; FILE *fd; char *z, *t; star = slash = run = ru = prun = r = comment = sqt = dqt = brace = dot = gotword = lastout = 0; *uqlist = ','; *(uqlist+1) = '\0'; lastch = '\0'; *word = *zfname = '\0'; skiph = header && level; if (recurse && level > MAXLVL) { fprintf(stdout, "** Maximum recursion depth exceeded - ignoring %s\n", fname); return 0; } if (recurse && ((int)(strlen(path) + strlen(fname)) > MAXPATH - 1)) { fprintf(stdout, "** Recursion too deep - leaving %s\n", fname); return 0; } ok = i = 0; if (search) strcpy(tpath,spath); do { if (search && i > 0) { strcpy(tname, t); strcat(tname, "/"); strcat(tname, fname); } else strcpy(tname, fname); if (access(tname, F_OK) == 0) { if (stat(tname, &buf) == 0) if (!(buf.st_mode & S_IFREG)) { fprintf(stdout, "** %s is not a regular text file.\n", tname); return 0; } if ((fd = fopen(tname,"r")) == NULL) { fprintf(stdout, "** Can't open %s\n", tname); return 0; } else { ok = 1; break; } } if (!search) break; if (i==0) t = strtok(tpath,","); else t = strtok(NULL,","); ++i; } while (t); if (!ok) { fprintf(stdout, "** %s not found.\n", fname); return 0; } if (recurse) { if (level == 0) { strcpy(path,","); strcat(path, fname); } else { strcpy(zfname,","); strcat(zfname, fname); strcat(zfname,","); if (strstr(path, zfname) != NULL) { fprintf(stdout, "** Endless recursion detected - backing out of %s\n", fname); fclose(fd); return 0; } strcat(path, fname); } strcat(path,","); } if (full && list) printf("%s: ", fname); while (ch = fgetc(fd), !feof(fd)) { if (full && list && lastout == '\n') { printf("%s: ", fname); lastout = 0; } if (full && !skiph) { putchar(ch); lastout = ch; } if (star && ch == '/') { star = comment = 0; continue; } star = (ch == '*'); if (comment) continue; if (ch == '\'' && !dqt) sqt = !sqt; if (ch == '"' && !sqt) dqt = !dqt; if (sqt || dqt) continue; if (ch == '/') if ((ch = fgetc(fd)) == '*') { if (full && !skiph) { putchar(ch); lastout = ch; } comment = 1; continue; } else { (void) ungetc(ch, fd); ch = '/'; } if (program && prun && isspace(ch)) { run = 1; prun = 0; *word = '\0'; w = 0; continue; } prun = (ru && ch == 'n'); ru = (r && ch == 'u'); r = (isspace(lastch) && ch == 'r'); lastch = ch; if (isspace(ch) && skiph && full) continue; if (full && skiph) { putchar(ch); lastout = ch; } skiph = 0; if (!brace && ch == '{') { ++brace; *word = '\0'; w = 0; continue; } if (brace || run) { if (isspace(ch) || ch == '}') { if (*word == '\0') { if (--brace < 0) brace = 0; continue; } else { if (*word == '&' || isdigit(*word) || *word == '*') { w = 0; *word = '\0'; if (--brace < 0) brace = 0; run = 0; gotword = 0; continue; } if (brace && ch != '}' || run && !dot) { gotword = 1; continue; } word[w] = '\0'; if (--brace < 0) brace = 0; if (run && word[strlen(word) - 1] == '.') word[strlen(word)-1] = '\0'; run = 0; gotword = 0; strcpy(zfname,","); strcat(zfname, word); strcat(zfname,","); if (!(ignore && strstr(iglist, zfname) != NULL) && !(unique && strstr(uqlist, zfname) != NULL)) { if (unique) { strcat(uqlist, word); strcat(uqlist, ","); } if (!full) { for (i=0;i INCLUDING %s (Level %d) <==========\n",word,level); if (scan(word, level + 1) == 1) { strcpy(zfname,","); strcat(zfname,word); strcat(zfname,","); z = strstr(path, zfname); *(z+1) = '\0'; } if (full) printf("==========> RETURNED FROM %s (Level %d) <==========\n\n",word,level); } } w = 0; continue; } } if (!gotword && ch != '{') word[w++] = ch; } dot = (ch == '.'); } fclose(fd); return 1; }