# /* * G E T C M D */ /*)BUILD $(TKBOPTIONS) = { TASK = ...GTC } */ #ifdef DOCUMENTATION title getcmd Build command files for Decus C index Build command files for Decus C synopsis getcmd >result -options pattern file_list description Getcmd was written to aid in maintaining the Decus C compiler. It is used to generate command files for building the run-time library, for example. It is probably of limited use in other areas. .s The following options are defined: .lm +16 .s.i-16;-c Macro command file, (for run-time library build. This prevents compiling RSX.MAC and RT11.MAC. .s.i-16;-d Enable debug code. .s.i-16;-m model "model" replaces '?' in a pattern string. .s.i-16;-r For RT11, preface the output file with "R MACRO" and end it with "^C". .s.lm-16 If no pattern is present, patterns and wild-card descriptions will be read from the standard input. The input format is: .s output_file pattern input_spec. .s If the pattern begins with a blank, the current output_file (or stdout) will be used. If the pattern contains blanks, enclose it in quotes. .s If no input_spec is present, the line is copied to the output with no changes other than substitution for the model string. .s Within a pattern, the following strings have special meaning: .lm +8 .s.i -8;? Replaced by the last model string .s.i -8;*.* Replaced by the filename + extension .s.i -8;* Replaced by the filename only .s.lm -8 Note that the disk and [UIC,PPN] is never output. .s Unflagged arguments are wild-card file specifications. .s For example: .s getcmd >rilbas.cmd -c OBJ:*,LST:*=SRC:RT11,SRC:* *.MAC .s The above command line builds the assembly command file for the I/O library in RT11 mode. .s getcmd >tov.cmd VAX::[C.OTSIO]*.*/VA=[5,5]*.* [5,5]*.* .s The above command generates an indirect command file for RSTS/E DECnet. bugs getcmd was written to aid in maintaining the Decus C run-time library. It is fairly useless in other situations. The build program may be more generally useful. author Martin Minow #endif /* * Edit history * 0.0 ??-???-?? MM Invention * 0.1 5-May-81 JSL If no filespec on a line, just copy the pattern * 0.2 5-May-81 JSL If no model, leave ? alone instead of deleting it * 0.3 4-Jun-81 MM Changed iovtoa to fgetname */ char *documentation[] = { "Getcmd builds command files, writing them to the standard output. Usage:", " getcmd >result [flag] pattern wild_card_descriptions", "The following switches are defined:", " -c Macro command file, delete reference to RSX.MAC and RT11.MAC", " -d Debug mode", " -m model \"Model\" replaces '?' in the pattern string", " -r RT11 switch, preface output with R MACRO, end with ^C", "", "If no pattern is present, patterns and wild-card descriptions will", "be read from the standard input. The input format is:", " output_file pattern input_spec.", "If the pattern begins with a blank, the current output_file (or stdout)", "will be used. If the pattern contains blanks, enclose it in quotes.", "", "If no input_spec is present, the line is copied to the output with no", "changes other than substitution for the model string.", "", "Within a pattern, the following strings have special meaning:", " ? Replaced by the last model string", " *.* Replaced by the filename + extension", " * Replaced by the filename only", "Note that the disk and [UIC,PPN] is never output", "", "Unflagged arguments are wild-card file specifications", "", "For example:", " getcmd >[5,5]rilbas.cmd -c \"OBJ:*,LST:*=SRC:RT11,SRC:*\" [5,5]*.MAC", "The above command line builds the assembly command file for the I/O", "library in RT11 mode.", "", " getcmd >iotovm.cmd \"RDVAX::DB0:[C.OTSIO]*.*/VA=[5,5]*.*\" [5,5]*.*", " The above command generates an indirect command file for RSTS/E DECnet", 0 }; #include #define FALSE 0 #define TRUE 1 #define EOS 0 #define MAX_NAMES 500 /* Max. file names */ int debug; int macroflag; int rt11flag; char *model; char *pattern; char *wild_spec; char *out_spec; char fullname[81]; char filename[81]; char line[133]; /* Input text line */ char *text[MAX_NAMES]; /* store file names here */ char **ttop = text; /* Top of text pointer */ FILE *infd; main(argc, argv) int argc; char *argv[]; { register int c; register int i; register char *ap; if (argv[1][0] == '?' && argv[1][1] == EOS) { help(); exit(); } model = "?"; for (i = 1; i < argc; i++) { if (*(ap = argv[i]) == '-') { while ((c = tolower(*++ap)) != EOS) { switch (c) { case 'd': debug++; break; case 'c': macroflag++; break; case 'm': if (++i >= argc) usage("No arg after -m"); model = argv[i]; goto loop; case 'r': rt11flag++; printf("R MACRO\n"); break; default: bug("W", "Unknown switch", ap); break; } } } else { if (pattern == NULL) { pattern = argv[i]; continue; } wild_spec = argv[i]; ttop = text; if (process() > 0) doit(); } loop:; } /* * pattern will be NULL if none was provided by the command line */ if (pattern == NULL) getinput(); if (rt11flag) printf("^C\n"); } getinput() /* * Read from stdin, process each line as it comes */ { register char *lp; register int c; register int count; char *skipbl(); char *findbl(); int fspecs; while (fgetss(line, sizeof line, stdin) != NULL) { /* * Skip over leading blanks and get file spec. */ fspecs = count = 0; ttop = text; lp = line; if (*lp > ' ') { out_spec = lp = skipbl(line); lp = findbl(lp); if (debug) fprintf(stderr, "new stdout = \"%s\"\n", out_spec); if (freopen(out_spec, "w", stdout) == NULL) { bug("E", "Can't open output file", out_spec); error("Can't continue"); } } /* * Skip over blanks and get pattern */ lp = findqbl(lp, &pattern); lp = skipbl(lp); while (*lp != EOS) { lp = findqbl(lp, &wild_spec); count += process(); fspecs++; } if (fspecs == 0) { /* No filespecs found */ cpystr(fullname,"*.*"); save(fullname); } if (count > 0 || fspecs == 0) doit(); } } process() /* * Find files, return how many */ { register int count; /* Count files */ if (debug) fprintf(stderr, "Wild card spec = \"%s\"\n", wild_spec); if ((infd = fwild(wild_spec, "r")) == NULL) { bug("E", "Can't open", wild_spec); return(0); } for (count = 0; fnext(infd) != NULL; count++) { setname(infd); if (debug) fprintf(stderr, "Curr file = \"%s\"\n", fullname); if (macroflag && (streq(fullname, "RSX.MAC") || streq(fullname, "RT11.MAC"))) continue; save(fullname); } if (debug) fprintf(stderr, "%d files processed\n\n", count); if (count == 0) bug("W", "No files matched", wild_spec); return(count); } doit() { register char **textp; /* Pointer to names */ register char *pp; /* Pattern pointer */ register int c; /* Current character */ for (textp = text; textp < ttop; textp++) { /* * Get file name part, too */ strcpy(filename, *textp); for (pp = filename; (c = *pp) != EOS && c != '.'; pp++); *pp = EOS; for (pp = pattern; (c = *pp++) != EOS;) { switch (c) { case '*': if (*pp == '.' && pp[1] == '*') { printf(*textp); pp += 2; } else printf(filename); break; case '?': printf(model); break; default: putchar(c); } } putchar('\n'); free(*textp); } } setname(fd) FILE *fd; /* * Build file name */ { register char *wp; register int c; char work[81]; fgetname(fd, work); /* * Skip backwards to the rightmost colon in the device name. */ for (wp = &work[strlen(work)]; wp > work && wp[-1] != ':'; wp--); /* * Skip over [UIC] or [PPN] if present */ if (*wp == '[' || *wp == '(') { while ((c = *wp++) != EOS && c != ']' && c != ')'); if (c == 0) { fprintf(stderr, "?GETCMD-bad file name \"%s\"\n", work); wp--; } } strcpy(fullname, wp); /* * Don't include version */ for (wp = fullname; (c = *wp) != EOS && c != ';'; wp++); *wp = EOS; } save() /* * Save fullname, add it to the text area (in sorted order) */ { register char **textp; register char **insert; register int i; for (textp = text; textp < ttop; textp++) { if ((i = strcmp(*textp, fullname)) == 0) { fprintf("?GETCMD-E-Duplicate file name \"%s\"\n", fullname); return; } else if (i > 0) break; } insert = textp; textp = ttop; if (++ttop >= &text[MAX_NAMES]) error("?GETCMD-F-Too many file names, %d max.\n", MAX_NAMES); while (textp >= insert) { textp[1] = *textp; textp--; } if ((*insert = malloc(strlen(fullname) + 1)) == NULL) error("?GETCMD-F-No room for \"%s\"\n", fullname); strcpy(*insert, fullname); } findqbl(text_ptr, start) char *text_ptr; char **start; /* * Skip leading blanks, find text (handle quoted text strings) * return true start of text in start */ { register char *lp; register int c; char *skipbl(); char *findbl(); *start = lp = skipbl(text_ptr); if ((c = *lp) == EOS) return(lp); else if (c == '"') { lp++; *start = lp; while ((c = *lp) != EOS && c != '"') lp++; if (c == EOS) { bug("E", "Missing quote in pattern", pattern); return(lp); } *lp++ = EOS; } else lp = findbl(lp); if (debug) fprintf(stderr, "unscanned (return) = \"%s\"\n", lp); return(lp); } char * skipbl(text_ptr) char *text_ptr; /* * Skip over blanks */ { register char *tp; register int c; for (tp = text_ptr; (c = *tp) != EOS && c <= ' '; tp++); return(tp); } char * findbl(text_ptr) char *text_ptr; /* * Skip to the next blank, terminate the string and step the pointer */ { register char *tp; for (tp = text_ptr; *tp > ' '; tp++); if (*tp) *tp++ = EOS; return(tp); } help() /* * Give good help */ { register char **dp; for (dp = documentation; *dp; dp++) fprintf(stderr, "%s\n", *dp); } usage(s) char *s; { bug("E", s, NULL); fprintf(stderr, "For help, GETCMD ?\n"); exit(1); } bug(severity, mess, arg) char *severity; char *mess; char *arg; /* * Error messages */ { fprintf(stderr, "%cGETCMD-%s-%s", (*severity == 'W') ? '%' : '?', severity, mess); if (arg != NULL) fprintf(stderr, ": \"%s\"", arg); fprintf(stderr, "\n"); }