/* carl@SOL1.GPS.CALTECH.EDU (Carl J Lydick) / 4:30 pm Sep 6, 1990 Every once in awhile, somebody asks the question "can you modify LATSYM like you can PRTSMB?", and invariably gets lots of answers that say "no, you can't". Well, I've now got a hack such that the answer is "well, sort of". It's not a user-modifiable LATSYM, but it's the next-best thing (well, maybe it's even better than a way to user-modify LATSYM, given the bugs that keep showing up in LATSYM): a modification to PRTSMB that makes it function almost like LATSYM's supposed to (the "almost" is because my modified PRTSMB give up the connection to the printer after each job rather than waiting until there are no more printabe jobs in the queue). Since it's written as a user-modification of PRTSMB, it's obviously user-modifiable. The one (possibly unjustified) assumption that this hack makes is that there will be exactly one call to the OUTPUT routine with function PSM$K_WRITE (or PSM$K_WRITE_NOFORMAT) after the JOB_COMPLETION routine returns end-of-file. If anybody with fiche would care to dig into the guts of PRTSMB and let me know just how shaky this assumption is, I'd be grateful. Here's the modification: */ /******************************************************************************\ * PSMDEF.H -- Print Symbiont Modification definitions * \******************************************************************************/ #define PSM$K_CANCEL 1 #define PSM$K_CLOSE 2 #define PSM$K_FORMAT 3 #define PSM$K_OPEN 4 #define PSM$K_READ 5 #define PSM$K_GET_KEY 6 #define PSM$K_POSITION_TO_KEY 7 #define PSM$K_REWIND 8 #define PSM$K_WRITE 9 #define PSM$K_WRITE_NOFORMAT 10 #define PSM$K_WRITE_SUPPRESSED 11 #define PSM$K_PAUSE_TASK 12 #define PSM$K_RESET_STREAM 13 #define PSM$K_RESUME_TASK 14 #define PSM$K_START_STREAM 15 #define PSM$K_START_TASK 16 #define PSM$K_STOP_TASK 17 #define PSM$K_STOP_STREAM 18 #define PSM$K_PAGE_SETUP 1 #define PSM$K_PAGE_HEADER 2 #define PSM$K_LIBRARY_INPUT 3 #define PSM$K_INPUT_FILTER 4 #define PSM$K_MAIN_FORMAT 5 #define PSM$K_OUTPUT_FILTER 6 #define PSM$K_OUTPUT 7 #define PSM$K_JOB_SETUP 8 #define PSM$K_FORM_SETUP 9 #define PSM$K_JOB_FLAG 10 #define PSM$K_JOB_BURST 11 #define PSM$K_FILE_SETUP 12 #define PSM$K_FILE_FLAG 13 #define PSM$K_FILE_BURST 14 #define PSM$K_FILE_SETUP_2 15 #define PSM$K_MAIN_INPUT 16 #define PSM$K_FILE_INFORMATION 17 #define PSM$K_FILE_ERRORS 18 #define PSM$K_FILE_TRAILER 19 #define PSM$K_JOB_RESET 20 #define PSM$K_JOB_TRAILER 21 #define PSM$K_JOB_COMPLETION 22 #define PSM$K_PAGE_FOOTER 23 #define PSM$k_max 24 #define PSM$K_CC_INTERNAL 1 #define PSM$K_CC_IMPLIED 2 #define PSM$K_CC_FORTRAN 3 #define PSM$K_CC_PRINT 4 #define PSM$K_CC_MAX 5 /******************************************************************************\ * LATSMB.C -- User modification to PRTSMB to make it work like LATSYM * \******************************************************************************/ #include "$psmdef.h" latsmb_modify() { long latsmb_job_completion(), latsmb_output(); PSM$REPLACE(&PSM$K_JOB_COMPLETION, latsmb_job_completion); PSM$REPLACE(&PSM$K_OUTPUT, latsmb_output); PSM$PRINT(0, 0, 0); } #include descrip #include psmmsgdef long close_it; latsmb_job_completion(long *request_id, long *work_area, long *func, struct dsc$descriptor *funcdesc, long *funcarg) { static char eof[] = "\f"; static int sent_eof = 0; if(*func == PSM$K_READ) { if(sent_eof == 0) { funcdesc->dsc$b_class = DSC$K_CLASS_S; funcdesc->dsc$a_pointer = &eof; funcdesc->dsc$w_length = 1; sent_eof = 1; close_it = 1; return 1; } else return PSM$_EOF; } else if(*func == PSM$K_OPEN || *func == PSM$K_CLOSE) { sent_eof = 0; return 1; } else return PSM$_FUNNOTSUP; } #include dcdef #include dvidef #include iodef #include lpdef #include ssdef #include ttdef #include "$smbdef.h" #define ckstat(x) if(((STAT = x) & 7) != 1) return STAT latsmb_output(long *request_id, long *work_area, long *func, struct dsc$descriptor *funcdesc, long *funcarg) { struct { short stat, count; long not_used; } iosb; static long chan; long STAT, stats[4], i; static char buffer[64]; static $DESCRIPTOR(devnam, buffer); if(*func == PSM$K_OPEN) { long devclass, devdepend; struct { short buflen, itmcod; long bufadr, lenadr; } itmlst[3] = { { 4, DVI$_DEVCLASS | DVI$C_SECONDARY, &devclass, 0 }, { 4, DVI$_DEVDEPEND | DVI$C_SECONDARY, &devdepend, 0}, { 0, 0, 0, 0 } }; ckstat(SYS$GETDVIW(0, 0, funcdesc, itmlst, &iosb, 0, 0, 0)); if(devclass == DC$_LP) *funcarg = (devdepend & LP$M_LOWER) == 0 ? 0 : SMBMSG$M_LOWERCASE; else if(devclass == DC$_TERM) *funcarg = SMBMSG$M_TERMINAL | ((devdepend & TT$M_LOWER) == 0 ? 0 : SMBMSG$M_LOWERCASE) | ((devdepend & TT$M_MODEM) == 0 ? 0 : SMBMSG$M_REMOTE); else return SS$_IVDEVNAM; ckstat(SYS$ALLOC(funcdesc, 0, 0, 0, 0)); ckstat(SYS$ASSIGN(funcdesc, &chan, 0, 0)); for(i = 0; i < funcdesc->dsc$w_length; ++i) buffer[i] = funcdesc->dsc$a_pointer[i]; devnam.dsc$w_length = funcdesc->dsc$w_length; close_it = 0; } else if(*func == PSM$K_WRITE || *func == PSM$K_WRITE_NOFORMAT) { stats[0] = SYS$QIOW(0, chan, *func == PSM$K_WRITE ? IO$_WRITELBLK : IO$_WRITEPBLK, &iosb, 0, 0, funcdesc->dsc$a_pointer, funcdesc->dsc$w_length, 0, 0, 0, 0); stats[1] = iosb.stat; stats[2] = stats[3] = 1; if (close_it == 1) { stats[2] = SYS$QIOW(0,chan,IO$_TTY_PORT|IO$M_LT_DISCON,&iosb, 0,0,0,0,0,0,0,0); if (stats[2] == SS$_ILLIOFUNC) stats[2] = stats[3] = 1; else stats[3] = iosb.stat; close_it = 0; } ckstat(stats[0]); ckstat(stats[1]); ckstat(stats[2]); ckstat(stats[3]); } else if(*func == PSM$K_CLOSE) { SYS$DASSGN(chan); ckstat(SYS$DALLOC(&devnam, 0)); } else if(*func != PSM$K_CANCEL) return PSM$_FUNNOTSUP; return 1; } /* ---------- */