/* 7 MAY 81 */ /* based on the formatter presented in Kernighan and Plauger's SOFTWARE TOOLS, modified for BDS C */ #include "ROFF.H" main(argc, argv) int argc; char **argv; { char filename[20], line[ MAXLINE ]; struct _buf iobuf; dioinit (&argc, argv); /* directed I/O */ fprintf(STDERR,"\nVersion 5.1\n"); while (0) putchar('\7'); debug = FALSE; if (argc == 1) { fprintf(STDERR,"\nUSAGE: format file1\n more than one file OK "); exit(); } argv++; while ( --argc > 0 ) { strcpy (filename, *argv++); /* get next argument */ fprintf(STDERR,"\nNow processing <%s>",filename ); if (filename[0] == '-' && filename[1]=='D') { debug=TRUE; continue; } if (ERROR == fopen( filename, &iobuf )) { fprintf(STDERR,"\ncan not open <%s>", filename ); continue; } init_defaults(); while ( fgets( line, &iobuf ) != 0 ) /*until EOF or CPMEOF */ { if (line[0] == COMMAND ) comand (line); else text (line); } if (LINENO > 0 || OUTBUF[0] !='\0') space (HUGE); /* flush last output */ fprintf(STDERR,"\nDone processing <%s>", filename ); } /* end while (--argc > 0 ) */ dioflush(); } /* end main() */ /******************************************************************** initializes the global variables governing the execution of the format commands. ********************************************************************/ init_defaults() { FILL = FI_DEF; /* yes we want filled lines */ LSVAL = LS_DEF; /* line spacing = 1 */ INVAL = IN_DEF; /* left margin indent 0 */ RMVAL = RM_DEF; /* right margin = page width */ TIVAL = TI_DEF; /* left margin temporary indent 0 */ CEVAL = CE_DEF; /* next n lines to be centered - 0 */ ULVAL = UL_DEF; /* next n lines to be underlined - 0 */ PAGESTOP = FALSE; PLVAL = PAGELEN; M1VAL = M1_DEF; /* top and bottom margins */ M2VAL = M2_DEF; M3VAL = M3_DEF; M4VAL = M4_DEF; CURPAG = 0; NEWPAG = 1; LINENO = 0; BOTTOM = PLVAL - M3VAL - M4VAL; OUTWRDS = 0; /* no. of words in outbuf */ OUTBUF [0] = '\0'; DIR = 0; strcpy ( HEADER, "\n" ); strcpy ( FOOTER, "\n" ); } /***************************************************************** this function decodes the command type, returning the type, or UNKNOWN. *******************************************************************/ int comtyp (line) char *line; { char let1, let2; let1 = toupper( line[1] ); let2 = toupper( line[2] ); if ( let1=='F' && let2=='I') return( FI ); if ( let1=='F' && let2=='O') return( FO ); if ( let1=='T' && let2=='I') return( TI ); if ( let1=='B' && let2=='P') return( BP ); if ( let1=='B' && let2=='R') return( BR ); if ( let1=='C' && let2=='E') return( CE ); if ( let1=='H' && let2=='E') return( HE ); if ( let1=='I' && let2=='N') return( IN ); if ( let1=='L' && let2=='S') return( LS ); if ( let1=='N' && let2=='F') return( NF ); if ( let1=='P' && let2=='L') return( PL ); if ( let1=='R' && let2=='M') return( RM ); if ( let1=='S' && let2=='P') return( SP ); if ( let1=='U' && let2=='L') return( UL ); if ( let1=='M') { if (let2=='1') return( M1 ); if (let2=='2') return( M2 ); if (let2=='3') return( M3 ); if (let2=='4') return( M4 ); } return( UNKNOWN ); /* no match */ } /********************************************************************* Skips white-space characters at the beginning of a string. *********************************************************************/ skip_blanks ( string ) char *string; { char local[ MAXLINE ]; int i, j, k; strcpy ( local, string ); for (i=0; local[i]==' ' || local[i]=='\t' || local[i]=='\n' ; i++); for (j=0; (string[j]=local[i]) != '\0' ; i++, j++ ) ; return; } /********************************************************************* Truncates white-space characters at the end of a string. *********************************************************************/ trunc_bl (string) char *string; { char *ptr; int k; k = strlen (string); ptr = &string[ k-1 ]; /* char before terminating nul */ while (*ptr==BLANK || *ptr==TAB || *ptr==NEWLINE) *ptr-- = '\0'; } /******************************************************************* performs the formatting command returned by comtyp - sets global variables ( indenting, underlining, etc. ) *******************************************************************/ comand ( line ) char *line; { int c_type; /* command type */ int arg_val; /* argument value, if any */ char arg_typ; /* relative (+ or -) or absolute */ int i; c_type = comtyp (line); if DEBUG fprintf(STDERR,"\n\nCOMAND %d",c_type); if (c_type == UNKNOWN) /* IGNORE ALIEN ORDERS */ { fprintf(STDERR, "UNKNOWN COMMAND: <%s>\n", line); return; } arg_val = get_val ( line, &arg_typ ); if DEBUG fprintf(STDERR, " \n get_val returned arg_val=%d, arg_typ= %c ", arg_val, arg_typ ); if DEBUG fprintf(STDERR,"\n\n"); switch (c_type) { case FI : /* filled lines */ brk(); /* flush out last unfilled */ FILL = YES; break; case NF : /* non-filled lines */ brk(); /* flush out */ FILL = NO; break; /* down and cry */ case BR : /* just cause a break */ brk(); break; case LS : /* set line spacing value */ set (&LSVAL, arg_val, arg_typ, LS_DEF, 1, HUGE ); break; case TI : /* set temporary left indent */ brk(); set ( &TIVAL, arg_val, arg_typ, TI_DEF, 0, RMVAL ); break; case IN : /* set left indent */ set ( &INVAL, arg_val, arg_typ, IN_DEF, 0, RMVAL-1 ); TIVAL = INVAL; break; case RM: /* set right margin */ set ( &RMVAL, arg_val, arg_typ, RM_DEF, TIVAL+1, HUGE ); break; case M1: /* set topmost margin */ set ( &M1VAL, arg_val, arg_typ, M1_DEF, 0, HUGE); break; case M2: /* set second top margin */ set ( &M2VAL, arg_val, arg_typ, M2_DEF, 0, HUGE); break; case M3: /* set first bottom margin */ set ( &M3VAL, arg_val, arg_typ, M3_DEF, 0, HUGE); break; case M4: /* set bottom-most margin */ set ( &M4VAL, arg_val, arg_typ, M4_DEF, 0, HUGE); break; case CE : /* center next arg_val lines */ brk(); set ( &CEVAL, arg_val, arg_typ, CE_DEF, 0, HUGE); break; case UL : /* underline next arg_val lines */ set ( &ULVAL, arg_val, arg_typ, UL_DEF, 1, HUGE ); break; case HE : /* get header title for pages */ gettl ( line, HEADER ); break; case FO : /* get footer title for pages */ gettl ( line, FOOTER ); break; case SP : /* space down arg_val blank lines */ set (&SPVAL, arg_val, arg_typ, 1, 0, HUGE); space ( SPVAL ); break; case BP : /* set pageno arg_val - begin page */ if ( LINENO > 0 ) space (HUGE); set ( &CURPAG, arg_val, arg_typ, CURPAG+1, -HUGE, HUGE); NEWPAG = CURPAG; break; case PL : /* set page length */ set (&PLVAL, arg_val, arg_typ, PAGELEN, M1VAL+M2VAL+M3VAL+M4VAL+1, HUGE); BOTTOM = PLVAL - M3VAL - M4VAL; break; } return; } /****************************************************************** gets the number ( if any ) associated with any command *******************************************************************/ int get_val ( line, typ ) char *line, *typ; { int i; char local[ MAXLINE ]; strcpy (local, line); /* local copy */ /* skip over the command line */ for (i=1; local[i]!=' ' && local[i]!='\t' && local[i]!='\n' ; i++ ) ; skip_blanks (&local[i]); /* find the number */ *typ = local[i]; /* relative or absolute */ if ( *typ=='+' || *typ=='-' ) i++; else if ( !isdigit( *typ ) ) return( NO_VAL ); return ( atoi( &local[i] )); } /***************************************************************** sets a global parameter like line-spacing, underlining, etc. Also checks that the new value is within the range of that parameter. Assigns the default for that parameter if no value is specified. ******************************************************************/ set ( param, val, arg_typ, defval, minval, maxval ) int *param, val, defval, minval, maxval; char arg_typ; { if (val == NO_VAL ) /* defaulted */ *param = defval; else if (arg_typ == '+') /* relative + */ *param += val; else if (arg_typ == '-') /* relative - */ *param -= val; else *param = val; /* absolute */ *param = min (*param,maxval); *param = max (*param, minval); if DEBUG fprintf(STDERR,"\n SET *param = %d", *param); return; } /********************************************************** centers a line of text **********************************************************/ center (line) char *line; { TIVAL = max(( RMVAL+TIVAL-strlen(line))/2, 0 ); return; } /************************************************************** get next word from input line ***************************************************************/ int getwrd (in, out ) char *in, *out; { int i, j, n; /* find first non-blank */ skip_blanks (in); replace_char ( in, TAB, BLANK); /* replace tabs w/space */ /* scan off a word */ if ( 1 == (n = sscanf( in, "%s ", out))) { if DEBUG fprintf(STDERR,"\nafter sscanf out = <%s>",out); j = strlen (out); replace_char (out, NEWLINE, BLANK); for (i=0; i, nextra=%d, no_words=%d", line, nextra, no_words ); if (nextra <= 0 || no_words <= 1) return; DIR = !(DIR); nholes = no_words - 1; trunc_bl (line); i = strlen(line) - 1 ; /* last character of string */ j = min (MAXLINE - 2, i + nextra); /* last position in output */ line[j+1] = '\0'; if DEBUG fprintf(STDERR,"\nDIR=%d, nholes=%d, i=%d, j=%d", DIR, nholes, i, j ); for ( ; i 0; nblanks-- ) line[--j] = BLANK; } } if DEBUG fprintf(STDERR,"\nafter spreading, line is:\n<%s>", line); return; } /**************************************************************** end current filled line *****************************************************************/ brk() { int l; if DEBUG fprintf(STDERR,"\nbrk: OUTBUF=<%s>", OUTBUF); if ( 0!= ( l = strlen (OUTBUF))) { OUTBUF[l] = NEWLINE; OUTBUF[l+1] = '\0'; put (OUTBUF); } OUTWRDS = 0; OUTBUF[0] = '\0'; return; }