/* B B A N - A Better Banner Program - Apr84 IBM-PC version */ /* The vax version will not work directly on the PC, because the ** UNIX shell metacharacter interpretation caused strings like ** 'one two three' to be passed as a single command line arg, while ** under DOS, it becomes three: "'one", "two", and "three'" ** So, we need a scheme for embedding spaces in arguments. ** One: choose some other character like underscore '_' and after ** command line argument passing, translate it into a space. ** Two: alter the program logic to treat single and double ** quotes as delimiters, and keep concatenating DOS-passed arguments ** until the closing delimiter is detected. ** Two is more elegant, but One is easier. */ #include #include #if defined(__STDC__) || defined(__cplusplus) # define P_(s) s #else # define P_(s) () #endif /* banner.c */ extern int main P_((int argc, char **argv)); static void doline P_((void)); static int aqarg P_((void)); static int redarg P_((void)); static int gint P_((char **pp)); #undef P_ /* table of character translation patterns */ char ctbl[128][7] = { /* stolen from banner */ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /*below 040*/ { 0, 000, 000, 000, 000, 000, 000 }, /* */ { 034, 034, 034, 010, 0, 034, 034 }, /*!*/ { 0167, 0167, 042, 0, 0, 0, 0 }, /*"*/ { 024, 024, 0177, 024, 0177, 024, 024 }, /*#*/ { 076, 0111, 0110, 076, 011, 0111, 076 }, /*$*/ { 0161, 0122, 0164, 010, 027, 045, 0107 }, /*%*/ { 030, 044, 030, 070, 0105, 0102, 071 }, /*&*/ { 034, 034, 010, 020, 0, 0, 0 }, /*'*/ { 014, 020, 040, 040, 040, 020, 014 }, /*(*/ { 030, 4, 2, 2, 2, 4, 030 }, /*)*/ { 0, 042, 024, 0177, 024, 042, 0 }, /***/ { 0, 010, 010, 076, 010, 010, 0 }, /*+*/ { 0, 0, 0, 034, 034, 010, 020 }, /*,*/ { 0, 0, 0, 076, 0, 0, 0 }, /*-*/ { 0, 0, 0, 0, 034, 034, 034 }, /*.*/ { 1, 2, 4, 010, 020, 040, 0100 }, /*SLASH*/ { 034, 042, 0101, 0101, 0101, 042, 034 }, /*0*/ { 010, 030, 050, 010, 010, 010, 076 }, /*1*/ { 076, 0101, 1, 076, 0100, 0100, 0177 }, /*2*/ { 076, 0101, 1, 076, 1, 0101, 076 }, /*3*/ { 0100, 0102, 0102, 0102, 0177, 2, 2 }, /*4*/ { 0177, 0100, 0100, 0176, 1, 0101, 076 }, /*5*/ { 076, 0101, 0100, 0176, 0101, 0101, 076 }, /*6*/ { 0177, 0102, 04, 010, 020, 020, 020 }, /*7*/ { 076, 0101, 0101, 076, 0101, 0101, 076 }, /*8*/ { 076, 0101, 0101, 077, 1, 0101, 076 }, /*9*/ { 010, 034, 010, 0, 010, 034, 010 }, /*:*/ { 034, 034, 0, 034, 034, 010, 020 }, /*;*/ { 020, 010, 4, 2, 4, 010, 020 }, /*<*/ { 0, 0, 076, 0, 076, 0, 0 }, /*=*/ { 4, 010, 020, 040, 020, 010, 4 }, /*>*/ { 076, 0101, 1, 016, 010, 0, 010 }, /*?*/ { 076, 0101, 0135, 0135, 0136, 0100, 076 }, /*@*/ { 010, 024, 042, 0101, 0177, 0101, 0101 }, /*A*/ { 0176, 0101, 0101, 0176, 0101, 0101, 0176 }, /*B*/ { 076, 0101, 0100, 0100, 0100, 0101, 076 }, /*C*/ { 0176, 0101, 0101, 0101, 0101, 0101, 0176 }, /*D*/ { 0177, 0100, 0100, 0174, 0100, 0100, 0177 }, /*E*/ { 0177, 0100, 0100, 0174, 0100, 0100, 0100 }, /*F*/ { 076, 0101, 0100, 0117, 0101, 0101, 076 }, /*G*/ { 0101, 0101, 0101, 0177, 0101, 0101, 0101 }, /*H*/ { 034, 010, 010, 010, 010, 010, 034 }, /*I*/ { 1, 1, 1, 1, 0101, 0101, 076 }, /*J*/ { 0102, 0104, 0110, 0160, 0110, 0104, 0102 }, /*K*/ { 0100, 0100, 0100, 0100, 0100, 0100, 0177 }, /*L*/ { 0101, 0143, 0125, 0111, 0101, 0101, 0101 }, /*M*/ { 0101, 0141, 0121, 0111, 0105, 0103, 0101 }, /*N*/ { 0177, 0101, 0101, 0101, 0101, 0101, 0177 }, /*O*/ { 0176, 0101, 0101, 0176, 0100, 0100, 0100 }, /*P*/ { 076, 0101, 0101, 0101, 0105, 0102, 075 }, /*Q*/ { 0176, 0101, 0101, 0176, 0104, 0102, 0101 }, /*R*/ { 076, 0101, 0100, 076, 1, 0101, 076 }, /*S*/ { 0177, 010, 010, 010, 010, 010, 010 }, /*T*/ { 0101, 0101, 0101, 0101, 0101, 0101, 076 }, /*U*/ { 0101, 0101, 0101, 0101, 042, 024, 010 }, /*V*/ { 0101, 0111, 0111, 0111, 0111, 0111, 066 }, /*W*/ { 0101, 042, 024, 010, 024, 042, 0101 }, /*X*/ { 0101, 042, 024, 010, 010, 010, 010 }, /*Y*/ { 0177, 2, 4, 010, 020, 040, 0177 }, /*Z*/ { 076, 040, 040, 040, 040, 040, 076 }, /*[*/ { 0100, 040, 020, 010, 004, 002, 001 }, /*\*/ { 076, 2, 2, 2, 2, 2, 076 }, /*]*/ { 010, 024, 042, 0, 0, 0, 0 }, /*^*/ { 0, 000, 000, 000, 000, 000, 0177 }, /*_*/ { 034, 034, 010, 04, 0, 0, 0 }, /*`*/ { 0, 014, 022, 041, 077, 041, 041 }, /*a*/ { 0, 076, 041, 076, 041, 041, 076 }, /*b*/ { 0, 036, 041, 040, 040, 041, 036 }, /*c*/ { 0, 076, 041, 041, 041, 041, 076 }, /*d*/ { 0, 077, 040, 076, 040, 040, 077 }, /*e*/ { 0, 077, 040, 076, 040, 040, 040 }, /*f*/ { 0, 036, 041, 040, 047, 041, 036 }, /*g*/ { 0, 041, 041, 077, 041, 041, 041 }, /*h*/ { 0, 004, 004, 004, 004, 004, 004 }, /*i*/ { 0, 001, 001, 001, 001, 041, 036 }, /*j*/ { 0, 041, 042, 074, 044, 042, 041 }, /*k*/ { 0, 040, 040, 040, 040, 040, 077 }, /*l*/ { 0, 041, 063, 055, 041, 041, 041 }, /*m*/ { 0, 041, 061, 051, 045, 043, 041 }, /*n*/ { 0, 036, 041, 041, 041, 041, 036 }, /*o*/ { 0, 076, 041, 041, 076, 040, 040 }, /*p*/ { 0, 036, 041, 041, 045, 042, 035 }, /*q*/ { 0, 076, 041, 041, 076, 042, 041 }, /*r*/ { 0, 036, 040, 036, 001, 041, 036 }, /*s*/ { 0, 037, 004, 004, 004, 004, 004 }, /*t*/ { 0, 041, 041, 041, 041, 041, 036 }, /*u*/ { 0, 041, 041, 041, 041, 022, 014 }, /*v*/ { 0, 041, 041, 041, 055, 063, 041 }, /*w*/ { 0, 041, 022, 014, 014, 022, 041 }, /*x*/ { 0, 021, 012, 004, 004, 004, 004 }, /*y*/ { 0, 077, 002, 004, 010, 020, 077 }, /*z*/ { 034, 040, 040, 0140, 040, 040, 034 }, /*{*/ { 010, 010, 010, 0, 010, 010, 010 }, /*|*/ { 034, 2, 2, 3, 2, 2, 034 }, /*}*/ { 060, 0111, 06, 0, 0, 0, 0 }, /*~*/ { 0, 000, 000, 000, 000, 000, 000 }, /*DEL*/ }; /* string sizes that fit selected printer widths: flag/size/-w=> 72 80 81 120 132 158 174 217 225 -hj 8 9 10 10 15 16 19 21 27 28 -ho 9 8 8 9 13 14 17 19 24 25 -fj 15 4 5 5 8 8 10 11 14 15 -fo 16 4 5 5 7 8 9 10 13 14 note: -jn "lower case" is similar to -on "CAPS" */ /* table of parameter default values */ int dw = 80; /* page width, print positions */ int di = 0; /* indent, print positions */ int db = 0; /* print blank lines before arg */ /* negative numbers require use of col */ int dnp = 0200; /* contrast: 0200 -> pos, 0 -> neg */ int doj = 0; /* spacing: 0 -> open, 1 -> jammed */ int dclr = 8; /* justification: 8 -> left, 1 -> center, 0 -> right */ int dtv = 0; /* vert size: 0 -> normal, 7 -> double */ int dfh = 0; /* hor size: 0 -> normal, 7 -> double */ int dex = 1; /* echo: 1 -> expand, 0 -> copy thru */ int dau = 1; /* mark case: 1 -> caps, 0 -> asis */ int dkd = 0; /* mark string: 0 -> pmark, 1 -> self */ char dmark[31] = ""; /* marking chars - used serially */ /* parameters to use for current line */ int pw, pi, pb, pnp, poj, pclr, ptv, pfh, pex, pau, pkd; char *pms, pmark[31]; /* global variables */ char *arg, ioarg1[121], ioarg2[121]; /* arg pointer, input areas */ int aargc; char **aargv; int vx, strl; char *chp, *esp, *imk, *mkp, *chh, mk; /* e.g: bban -nk " BBAN " BBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBB BANBBANBBA BAN ANBBAN BANBB NBBAN BANBBANBBA ANBBANBBAN BANBB NB ANBBA BBAN B NBBA BANB ANBBANBBAN NBBANBBANB ANBBA BB NBBAN BAN BAN BAN B NBB NBBANBBANB BBANBBANBB BBA BAN BANBB NB AN BA BBANBBANBB BANBBANBBA BBANB AN BANBB NB BB NBB N BANBBANBBA ANBBANBBAN BANBB NB ANBBA BB NBBAN BA BBAN ANBBANBBAN NBBANBBANB NBB BBA BBANB AN BANBB NBBANBBANB BBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBBANBB */ int main (int argc, char **argv) { int firstarg, i, ival, xvx, cwd; char *p, *q, ol[226], *ols; /* check for proper usage */ if (argc < 2) { printf ("Usage: bban [-abcdefghijklmnopqrstuvwx] textarg [-] [...]\n"); printf ("[-] interpolate from stdin into command line.\n"); printf ("-w# (Width) The page width is set to #.\n"); printf ("-i# (Indent) # extra blanks are left-inserted into each output line.\n"); printf ("-b# (Blank lines) # extra blank lines will be output before the text\n"); printf ("-lrc (Left, Right, Centered) ;justification of output\n"); printf ("-jo (Jammed,Open) -j) omit normal 1-space border on top & left\n"); printf ("-tv (Tall,Vertically normal)\n"); printf ("-fh (Fat,Horizontally normal) \n"); printf ("-ms (Mark string,Self) -m) next input arg. forms cyclic banner chars\n"); printf (" -s) each text argument character used in forming itself.\n"); printf ("-kd (marK,Default mark) use the text argument string to mark itself\n"); printf ("-au (Asis,Uppercase) affect marking characters from -s or -k\n"); printf ("-pn (Positive,Negative)\n"); printf ("-ex (Echo,eXpand)\n"); printf ("-g (Global) \n"); printf ("-q (Quit) \n"); printf ("The default flag settings are: -lovhsupxw120i0b0\n"); printf ("bban -jm # text (Gives results similar to the banner command)\n"); printf ("bban -m \\ EST -b-8ils EST \n"); printf ("bban -jmn NUTS <12 underscores> -tfow72 ____NUTS____ -w72 <12 more>'\n"); printf ("bban -j LO VE | bban -j -\n"); exit (1); } /* make cmd line args available to other routines */ aargc = argc; aargv = argv; /* set parameters to default values */ pw = dw; pi = di; pb = db; pnp = dnp; poj = doj; pclr = dclr; ptv = dtv; pfh = dfh; pex = dex; pau = dau; pkd = dkd; pms = dmark; imk = pms; /* loop on args from cmd line or std input */ firstarg = 1; while (aqarg () != 0) { if (*arg == '-') { /* analyze flag args */ p = arg; /* note q flag in loop condition */ while (*++p != '\0' && *p != 'q' && *p != 'Q') switch (*p) { case 'w': case 'W': if ((ival = gint (&p)) >= 1 && ival <= 225) pw = ival; else printf ("W flag needs numeric 1:225, e.g: -w80\n"); break; case 'i': case 'I': if ((ival = gint (&p)) >= 0) pi = ival; else printf ("I flag needs numeric >= 0, e.g: -i0\n"); break; case 'b': case 'B': pb = gint (&p); /* extra vertical spacing */ break; case 'n': case 'N': pnp = 0; /* contrast -> negative */ break; case 'p': case 'P': pnp = 0200; /* contrast -> positive */ break; case 'o': case 'O': poj = 0; /* spacing -> open */ break; case 'j': case 'J': poj = 1; /* spacing -> jammed */ break; case 'c': case 'C': pclr = 1; /* justification -> center */ break; case 'l': case 'L': pclr = 8; /* justification -> left */ break; case 'r': case 'R': pclr = 0; /* justification -> right */ break; case 't': case 'T': ptv = 7; /* height -> double */ break; case 'v': case 'V': ptv = 0; /* height -> normal */ break; case 'f': case 'F': pfh = 7; /* width -> double */ break; case 'h': case 'H': pfh = 0; /* width -> normal */ break; case 'e': case 'E': pex = 0; /* echo only - don't expand */ break; case 'x': case 'X': pex = 1; /* expand to banner size */ break; case 'g': case 'G': firstarg = 1; /* reset global defaults */ break; case 'a': case 'A': pau = 0; /* use chars asis for mark */ break; case 'u': case 'U': pau = 1; /* use upper case for mark */ break; case 'k': case 'K': pkd = 1; /* use string to mark itself */ break; case 'd': case 'D': pkd = 0; /* revert to default mark string */ break; case 's': case 'S': pmark[0] = '\0'; /* mark with self */ pms = pmark; pkd = 0; break; case 'm': case 'M': if (aqarg () == 0) { printf ("M flag needs mark string, e.g: -m ABC\n"); break; } for (i = 0; i < 30; i++) { if (*arg == '\0') break; if ((pmark[i] = *arg++) <= 040 || pmark[i] == 0177) i--; } pmark[i] = '\0'; pms = pmark; imk = pms; pkd = 0; break; default: /* there ain't many left! */ printf ("Illegal flag \"%c\", ignored\n", *p); } /*endswitch*/ if (firstarg) { /* reset defaults to first flag arg */ dw = pw; di = pi; db = pb; dnp = pnp; doj = poj; dclr = pclr; dtv = ptv; dfh = pfh; dex = pex; dau = pau; dkd = pkd; p = dmark; q = pmark; while ((*p++ = *q++) != '\0') ; pms = dmark; } } else { /* non-flag argument - print it */ /* determine string length and page positioning */ cwd = (pex) ? 9 + pfh - poj : 1; if (pw - pi < cwd) { printf ("-i%d and -w%d allow inadequate space\n", pi, pw); continue; } for (i = 0; i < pb; i++) printf ("\n"); for (i = 0; i > pb; i--) printf ("7"); /* esc-7 */ for (strl = 0; arg[strl]; strl++) ; if (strl * cwd > pw - pi) strl = (pw - pi) / cwd; ols = ol + pi + ((pw - pi - strl * cwd) >> pclr); for (p = ol; p < ols; p++) *p = ' '; /* blank l.h. margin */ if (pex) { /* expand chars to banner size */ if (pkd) { /* mark w/string itself */ p = arg; for (i = 0; i < 30; i++) { if (*p == '\0') break; /* patch to interpret underscores as spaces */ if (*p == '_') *p = ' '; pmark[i] = *p++; if (pmark[i] <= 040 || pmark[i] == 0177) i--; else if (pau && pmark[i] >= 'a' && pmark[i] <= 'z') pmark[i] -= ('a' - 'A'); } pmark[i] = '\0'; pms = pmark; imk = pms; } /* loop for each horizontal slice of chars */ for (vx = poj; vx <= 8; vx++) { for (xvx = 0; xvx <= ((vx & ptv) != 0); xvx++) { esp = ol; /* loc of newline */ chp = ols; /* start of 1st char */ doline (); /* format one line */ *esp = '\0'; printf ("%s\n", ol); /* VOLA!! */ *esp = ' '; if (*imk == '\0' || *++imk == '\0') imk = pms; } } } else { /* echo without expansion */ esp = ol; chp = ols; for (i = 0; i < strl; i++) { *chp = arg[i]; if (*chp++ != ' ') esp = chp; } *esp = '\0'; printf ("%s\n", ol); } /* reset parms to defaults */ pw = dw; pi = di; pb = db; pnp = dnp; poj = doj; pclr = dclr; ptv = dtv; pfh = dfh; pex = dex; pau = dau; pkd = dkd; if (pms != dmark) { pms = dmark; imk = pms; } } firstarg = 0; } for (i = 0; i < pb; i++) printf ("\n"); exit (0); } static void doline (void) { int cx, hx, xhx, chs; mkp = imk; for (cx = 0; cx < strl; cx++) { /* loop on chars */ chh = arg + cx; /* patch to convert underscores to spaces */ if (*chh == '_') *chh = ' '; chs = (vx & 7) ? ctbl[(*chh)&0x7F][vx - 1] : 0; /* convert mark to upper case */ mk = (pau && *chh >= 'a' && *chh <= 'z') ? *chh - ('a' - 'A') : *chh; for (hx = poj; hx <= 8; hx++) { /* vert slice */ for (xhx = 0; xhx <= ((hx & pfh) != 0); xhx++) { if (*pms) { /* cycle mark string */ mk = *mkp; if (*++mkp == '\0') mkp = pms; } *chp = ((chs << hx & 0200) == pnp) ? mk : ' '; if (*chp++ != ' ') esp = chp; } } } } static int aqarg (void) { static int dashsw = 0; if (--aargc > 0) { /* more cmd line args */ if (**++aargv != '-' || *(*aargv + 1) != '\0') { arg = *aargv; dashsw = 0; return 1; } else { /* lone dash - std input */ dashsw = 1; if (redarg ()) return 1; printf ("EOF on std input\n"); return 0; } } else { /* read input if dash last */ if (dashsw) return (redarg ()); arg = ioarg1; ioarg1[0] = '\0'; return 0; } } static int redarg (void) { static int c = 1, bufsw = 1; register int i; arg = (bufsw ^= 1) ? ioarg1 : ioarg2; arg[0] = '\0'; if (c == EOF) return 0; for (i = 0; i < 120; i++) { arg[i] = (c = getchar ()); if (c == '\n' || c == EOF) break; } arg[i] = '\0'; if (c == EOF) return 0; if (c == '\n') return 1; while ((c = getchar ()) != '\n' && c != EOF) ; return 1; } static int gint (char **pp) { int dsw = 0, rslt = 0; if (*(*pp + 1) == '-') { dsw = 1; (*pp)++; } while (*(*pp + 1) >= '0' && *(*pp + 1) <= '9') { (*pp)++; rslt = 10 * rslt + **pp - '0'; } if (dsw) return -rslt; return rslt; }