#-h- cform 276 asc 02-may-81 22:20:25 [002,100] ## cform common block for formletter tool # put on a file named 'cform' # Used only by form common /cform/ char1, char2 character char1 #character to indicate beginning of prompt; #init = LESS character char2 #character to terminate prompt; #init = GREATER #-h- form.r 3512 asc 02-may-81 22:20:27 [002,100] #-h- defns 212 asc 02-may-81 22:08:30 [002,100] define(MAXFILES,10) #number files allowed on command line define(MAXREPLY,5000) #maximum characters available in user's response define(MEM_SIZE,3000) # size of dynamic storage in words define(ESCAPE,MINUS) #-h- main 1005 asc 27-apr-81 14:39:52 [002,100] ## form - replace all instances of '<...>' in file with input from user DRIVER(form) character line(MAXLINE) integer getarg, open integer i, nfiles character fnames(FILENAMESIZE, MAXFILES) include cform DS_DECL(Mem, MEM_SIZE) string usestr "usage: form file ..." data char1 /LESS/ data char2 /GREATER/ call query(usestr) call tbinit(MEM_SIZE) # initialize tblook and tbinst block call pbinit # initialize push-back buffer nfiles = 0 for (i=1; getarg(i, line, MAXLINE) != EOF; i=i+1) { if (line(1) == MINUS & line(2) != EOS) char1 = line(2) else if (line(1) == PLUS) char2 = line(2) else { nfiles = nfiles + 1 if (nfiles > MAXFILES) call error ('too many file names') call scopy(line, 1, fnames(1, nfiles), 1) } } for (i=1; i<=nfiles; i=i+1) #loop through all files { int = open(fnames(1,i), READ) if (int == ERR) call cant(fnames(1,i)) call forml(int) call close(int) } if (i == 1) #no input file call error (usestr) DRETURN end #-h- forml 612 asc 27-apr-81 14:39:54 [002,100] ##forml - replace prompts with user input on file 'int' subroutine forml(int) integer int, tog integer ftok, guser, tblook character token(MAXLINE), defn(MAXREPLY) include cform tog = NO while (ftok(token, int, tog) != EOF) { if (tog == YES) #inside prompt { if (token(1) == char2) { tog = NO next } if (tblook(token, defn) == NO) { if (guser(token, defn) == EOF) break call tbinst(token, defn) } call putlin(defn, STDOUT) next } else if (token(1) == char1) { tog = YES next } call putlin(token, STDOUT) #output normal text } return end #-h- ftok 632 asc 27-apr-81 14:39:55 [002,100] ## ftok - pick up token for form letter integer function ftok(token, int, prflag) character token(ARB) integer int, prflag character ngetch include cform for (i=1; i< MAXREPLY; i=i+1) { ftok = ngetch(token(i), int) if (ftok == EOF | (prflag == NO & ftok == NEWLINE) | (i == 1 & ftok == char1) | (i == 1 & ftok == char2) ) break if (ftok == char1 | ftok == char2) #beginning of next token { call putbak(ftok) if (ftok == char2 & prflag == YES) token(i) = BLANK else i = i - 1 break } } if (i >=MAXREPLY) call error ("token too long.") token(i+1) = EOS return end #-h- guser 741 asc 27-apr-81 14:39:56 [002,100] ##guser - get form letter replacement text from user integer function guser(pstr, repl) character repl(ARB), pstr(ARB) integer getlin, prompt integer lth lth = 0 repeat { if (lth == 0) i = prompt(pstr, repl(lth+1), STDIN) else i = getlin(repl(lth+1), STDIN) if (i == EOF) break lth = lth + i if (lth >= MAXREPLY) #oops--too long { call remark ('truncating response') break } if (repl(lth) == NEWLINE & repl(lth-1) != ESCAPE) break #no more lth = lth - 1 repl(lth) = NEWLINE #remove the escape #and continue } if (repl(lth) == NEWLINE) #remove last NEWLINE lth = lth - 1 repl(lth+1) = EOS if (i == EOF) guser = EOF else guser = lth return end #-h- form.rof 1702 asc 11-may-81 11:27:41 [002,100] .pl 60 .bp .rm 70 .in 0 .he 'FORM'3/1/79'FORM' .fo ''-#-' .fi NAME .br .in 7 FORM -- produces form letter by prompting user for information .sp 1 .in SYNOPSIS .br .in 7 form [-c] [+c] [file ...] .sp 1 .in DESCRIPTION .br .in 7 Form reads input files and writes them to the standard output. Any time it encounters some characters surrounded by angle brackets ('<' and '>') it prints the string between the characters as a prompt to the user. It then reads from the standard input and replaces the bracketed string with what was read. Normally only one line of input is accepted from the standard input. However, a response can be continued on succeeding lines by terminating each line to be continued with a minus ('-'). The prompts inside the file may also span line boundaries if so desired. The user's answers to prompts are remembered, so duplicate prompts are replaced without repeating the prompt to the user. If the standard input is not a terminal, no prompts are issued. The '-c' flag may be used to reset the initial character signalling a prompt. The character 'c' then replaces the '<'. The '+c' flag may be used to reset the terminating character of a prompt. The character 'c' then replaces '>'. .br .sp 1 .in FILES .br .in 7 The user's terminal is opened at READ access. .sp 1 .in SEE ALSO .br .in 7 The Unix form-letter tool .br .sp 1 .in DIAGNOSTICS .br .in 7 If an input file cannot be opened, a message is printed and execution is terminated. A message is also printed if either the prompt or the response is too long for the tool's internal buffer. .sp 1 .in AUTHORS .br .in 7 .sp 1 Debbie Scherrer .sp 1 .in BUGS .br .in 7