home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume21 / ro / part01 next >
Text File  |  1990-02-05  |  56KB  |  2,124 lines

  1. Subject:  v21i003:  A text formatter with some nroff-like capabilities, Part01/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: tcamp@dukeac.UUCP (Ted A. Campbell)
  7. Posting-number: Volume 21, Issue 3
  8. Archive-name: ro/part01
  9.  
  10. ro is a text formatter with many of the capabilities of nroff.  It is
  11. based on a long line of CP/M and MSDOS formatters, going back to the ROFF
  12. formatter described in Kernigan and Plauger's <Software Tools.>  Makefiles
  13. are included for DOS and Unix.   Freeware.
  14.  
  15. #--------------------------------CUT HERE-------------------------------------
  16. #! /bin/sh
  17. #
  18. # This is a shell archive.  Save this into a file, edit it
  19. # and delete all lines above this comment.  Then give this
  20. # file to sh by executing the command "sh file".  The files
  21. # will be extracted into the current directory owned by
  22. # you with default permissions.
  23. #
  24. # The files contained herein are:
  25. #
  26. # -rw-r--r--  1 tcamp   users      2644 Nov 24 13:07 README
  27. # -rw-r--r--  1 tcamp   users     14206 Nov 24 12:50 ro.h
  28. # -rw-r--r--  1 tcamp   users     15015 Nov 24 12:49 ro.c
  29. # -rw-r--r--  1 tcamp   users      7405 Nov 24 12:50 ro_proc.c
  30. # -rw-r--r--  1 tcamp   users     11762 Nov 24 12:50 ro_macr.c
  31. #
  32. echo 'x - README'
  33. if test -f README; then echo 'shar: not overwriting README'; else
  34. sed 's/^X//' << '________This_Is_The_END________' > README
  35. Xro version 1.00 -- Release of Source Code
  36. X-----------------------------------------
  37. X
  38. X
  39. XDescription:
  40. X-----------
  41. X
  42. X"ro" is a text formatter with some of the capabilities 
  43. Xof the Unix (tm, AT&T) "nroff" text formatter.  It is 
  44. Xbased on an honorable tradition of CP/M and DOS formatters
  45. Xwhich go back to the ROFF formatter described in Kernigan 
  46. Xand Plauger's <Software Tools>.  It is copyrighted and 
  47. Xdistributed as "freeware," i.e., you can use it for any 
  48. Xpurpose as long as you don't make money off of it, or 
  49. Xtry to claim that you wrote it.  
  50. X
  51. XThe "ro.qrf" file will give an overview of the capabilities 
  52. Xof the formatter.  
  53. X
  54. XThe sourcecode has been compiled on an XT clone using 
  55. Xthe Microsoft QuickC (tm) compiler, and on the AT&T 
  56. XUnix PC and 3B15 computers using the stock Unix C 
  57. Xcompilers.  
  58. X
  59. X
  60. XFiles:
  61. X-----
  62. X
  63. X    ro.h        general include file
  64. X    ro.c        main program module
  65. X    ro_proc.c    various procedures
  66. X    ro_macr.c    macro procedures
  67. X    ro_dive.c    diversion procedures
  68. X    ro_word.c    word-handling procedures
  69. X    ro_text.c    text-handling procedures
  70. X    ro_setp.c    parameter setting procedures
  71. X    ro_outp.c    output procedures
  72. X
  73. X    Makefile    Unix makefile
  74. X    ro.mak        QuickC makefile
  75. X
  76. X    term.h        include file for filters
  77. X    termnull.c    null filter -- strips out all printer codes
  78. X    termansi.c    ANSI filter -- sets printer codes for ANSI terminal
  79. X    termnx10.c    NX10 filter -- sets printer codes for NX 10 printer
  80. X
  81. X    ro.doc        primary documentation in "ro" format
  82. X    ro.qrf        quick reference guide
  83. X    tmac.m        a macro package
  84. X    test.doc    test document showing use of end-note macros
  85. X    README        this document
  86. X
  87. X
  88. XReading and printing the manual:
  89. X-------------------------------
  90. X
  91. XThe manual (file "ro.doc") is in "ro" format, and must be read
  92. Xusing "ro" and a filter program.  If you have the Unix or DOS 
  93. Xpager "more" installed in your path, you can read it page-by-
  94. Xpage with the command
  95. X
  96. X    ro ro.doc | termnull | more
  97. X
  98. XIf your DOS computer has ANSI.SYS installed, or your Unix terminal
  99. Xsupports ANSI escape sequences, the following command will show 
  100. Xbold as bold and italics as underline:
  101. X
  102. X    ro ro.doc | termansi | more
  103. X
  104. XThe manual can br printed to any printer with the command(s):
  105. X
  106. X    ro ro.doc | termnull | lp        (Unix)
  107. X    ro ro.doc | termnull >prn        (DOS)
  108. X
  109. XWith the Star Micronics NX10 printer, you may substitute 
  110. X"termnx10" for "termnull" in the above command lines.  Instructions
  111. Xfor creating filters for other printers are included in "ro.doc".  
  112. X
  113. XBinaries:
  114. X-----------
  115. X
  116. XPC-compatible binaries have been posted to comp.binaries.ibm.pc.
  117. X
  118. X
  119. XCommunications:
  120. X--------------
  121. X
  122. XTed A. Campbell
  123. XBywater Software 
  124. XBox 4023 
  125. XDuke Station
  126. XDurham, NC  27706
  127. X
  128. XInternet:      tcamp@dukeac.ac.duke.edu
  129. XGENIE:        T.CAMPBELL1
  130. ________This_Is_The_END________
  131. if test `wc -l < README` -ne 95; then
  132.     echo 'shar: README was damaged during transit (should have been 95 bytes)'
  133. fi
  134. fi        ; : end of overwriting check
  135. echo 'x - ro.h'
  136. if test -f ro.h; then echo 'shar: not overwriting ro.h'; else
  137. sed 's/^X//' << '________This_Is_The_END________' > ro.h
  138. X/********************************************************/
  139. X/*                            */
  140. X/*    ro.h        General header file for ro    */
  141. X/*                            */
  142. X/*    ro version 1.00                    */
  143. X/*                            */
  144. X/*    Portions copyright (c) 1989 by Ted A. Campbell    */
  145. X/*        Bywater Software            */
  146. X/*        P. O. Box 4023                */
  147. X/*        Duke Station                */
  148. X/*        Durham, NC  27706            */
  149. X/*                            */
  150. X/*    Contains portions of ROFF4, Version 1.60    */
  151. X/*      (c) 1983, 4 by Ernest E. Bergmann               */
  152. X/*        Physics, Building #16            */
  153. X/*        Lehigh University            */
  154. X/*        Bethlehem, Pa. 18015            */
  155. X/*                            */
  156. X/*    Contains portions of ROFF4, Version 1.61    */
  157. X/*      (c) 1985 by Konrad Kwok                         */
  158. X/*        20 3rd Street, Section M        */
  159. X/*        Fariview Park,                */
  160. X/*        Hong Kong                */
  161. X/*                            */
  162. X/*    ro and its predecessor ROFF4 are based on     */
  163. X/*    the ROFF text processor described in Kernigan    */
  164. X/*    and Plauger's now-classic text <Software Tools> */
  165. X/*                            */
  166. X/* Permission is hereby granted for all commercial and    */
  167. X/* non-commercial reproduction and distribution of this */
  168. X/* material provided this notice is included.        */
  169. X/*                            */
  170. X/********************************************************/
  171. X
  172. X/************* INCLUDE FILES ****************************/
  173. X
  174. X#include "stdio.h"
  175. X#include "ctype.h"
  176. X#include "time.h"
  177. X
  178. X#ifdef __STDC__
  179. X#include "stdlib.h"
  180. X#include "malloc.h"
  181. X#else
  182. X#define size_t  int
  183. X#define time_t  long
  184. X#endif
  185. X
  186. X/****** PROGRAM DEFINITIONS *****************************/
  187. X
  188. X/***    User-Definable Options ***/
  189. X
  190. X#define NONROFF            /* allow non-nroff-standard features */
  191. X
  192. X/***    End of User-Definable Options ***/
  193. X
  194. X#define    ro_    X        /* shorten names for limited compilers */
  195. X
  196. X#define MAXLINE 255
  197. X#define TRUE 1
  198. X#define FALSE 0
  199. X#define ERROR (-1)
  200. X#define OK 0
  201. X
  202. X#define    TBUFSIZE    4096    /* Size of temporary holding buffer */
  203. X#define BACKSIZE        4096    /* Size of backup buffer */
  204. X#define STKSIZ          4
  205. X#define DEBUG           ( debug != 0 )
  206. X#define HUGE            135     /* generally large number */
  207. X#define LSZ             511     /* line buffer size*/
  208. X#define COMMAND         '.'     /* all commands starts with this */
  209. X
  210. X#define UNKNOWN         -1      /* returned if doesn't recg. command */
  211. X#define NO_VAL          -32760  /* returned when no argument w/commad */
  212. X#define WE_HAVE_A_WORD   1       /* returned by getwrd func. */
  213. X#define NO              0
  214. X#define YES             1
  215. X#define UNDERLINE       '\137'
  216. X
  217. X/***    Character Definitions */
  218. X
  219. X#define CR              0x0D
  220. X#define BACKSPACE       '\b'
  221. X#define BELL        '\007'
  222. X#define NUMSIGN         '#'     /* for title strings */
  223. X#define NEWLINE         '\n'
  224. X#define TAB             '\t'
  225. X#define BLANK           ' '
  226. X#define FORMF           0x0C    /* formfeed for printer */
  227. X#define    ESCAPE        0x1b    /* escape character */
  228. X#define SQUOTE          0x27    /* single quote */
  229. X#define DQUOTE          0x22    /* double quote */
  230. X#define    BACKSLASH    0x5c    /* backslash */
  231. X#define    PASSBACK    0xeee    /* a random large number to pass a literal 
  232. X                   backslash back into the input stream */
  233. X
  234. X/**    Single-character printer code designations ***/
  235. X
  236. X#define    ROMAN        'R'    /* Restore "roman" or "regular" font */
  237. X                /* Should turn off Bold and Italic */
  238. X#define    ITALIC        'I'    /* Switch to italics or underline */
  239. X#define    BOLD        'B'    /* Switch to bold */
  240. X#define    HALFUP        'u'    /* Half-line up */
  241. X#define    HALFDOWN    'd'    /* Half-line down */
  242. X
  243. X#define TRANSLATE     2     /* May 23, 1983*/
  244. X#define BLACK         1
  245. X#define WHITE         0
  246. X#define CONTROL     -1
  247. X#define SENTINEL     -2
  248. X#define HTAB        -3
  249. X#define OTHERS         -4
  250. X#define XCHAR         '-'
  251. X#define UCHAR         '_'
  252. X
  253. X/* defaults for global parameters */
  254. X
  255. X#define FI_DEF          1
  256. X#define LS_DEF          1
  257. X#define IN_DEF          0
  258. X#define RM_DEF          70
  259. X#define TI_DEF          0
  260. X#define CE_DEF          1
  261. X#define UL_DEF          -1
  262. X#define M1_DEF          2
  263. X#define M2_DEF          2
  264. X#define M3_DEF          2
  265. X#define M4_DEF          2
  266. X#define PL_DEF          66
  267. X#define FF_DEF          YES     /* .ff defaults to "on" */
  268. X#define FF_INI          NO      /* initial setting*/
  269. X#define SC_INI          BLANK
  270. X#define TS_DEF          8       /*standard tabsize*/
  271. X#define TC_DEF          '~'     /*translation flag default*/
  272. X#define CF_DEF          '^'     /*Dec 4*/
  273. X#define IC_DEF          '\\'
  274. X#define CW_DEF          12      /* 12/120" */
  275. X#define JU_INI          YES     /* right adjust (justification) */
  276. X#define    PO_DEF        0    /* page offset */
  277. X#define REGDEF          0       /*default for register var.*/
  278. X                                /*when .rg has no numeric arg*/
  279. X
  280. X#define REVSCROLL       FALSE
  281. X#define CANBS           FALSE
  282. X
  283. X#define FMAX            8       /* # of additional files open*/
  284. X
  285. X/* defaults for global parameters */
  286. X
  287. X#define FI_DEF          1
  288. X#define LS_DEF          1
  289. X#define IN_DEF          0
  290. X#define RM_DEF          70
  291. X#define TI_DEF          0
  292. X#define CE_DEF          1
  293. X#define UL_DEF          -1
  294. X#define M1_DEF          2
  295. X#define M2_DEF          2
  296. X#define M3_DEF          2
  297. X#define M4_DEF          2
  298. X#define PL_DEF          66
  299. X#define FF_DEF          YES     /* .ff defaults to "on" */
  300. X#define FF_INI          NO      /* initial setting*/
  301. X#define SC_INI          BLANK
  302. X#define TS_DEF          8       /*standard tabsize*/
  303. X#define TC_DEF          '~'     /*translation flag default*/
  304. X#define CF_DEF          '^'     /*Dec 4*/
  305. X#define IC_DEF          '\\'
  306. X#define CW_DEF          12      /* 12/120" */
  307. X#define JU_INI          YES     /*right justification*/
  308. X#define REGDEF          0       /*default for register var.*/
  309. X                                /*when .rg has no numeric arg*/
  310. X
  311. X#define REVSCROLL       FALSE
  312. X#define CANBS           FALSE
  313. X
  314. X#define FMAX            8       /* # of additional files open*/
  315. X
  316. X#define FI              1       /* fill lines */
  317. X#define TI              2       /* temporary indent */
  318. X#define BP              3       /* begin page  */
  319. X#define BR              4       /* causes break */
  320. X#define CE              5       /* center line(s) */
  321. X#define IN              7       /* left indent */
  322. X#define LS              8       /* line spacing */
  323. X#define NF              9       /* no fill */
  324. X#define PL              10      /* set page length */
  325. X#define LL              11      /* set line length (right margin) */
  326. X#define SP              12      /* add blank line(s) */
  327. X#define ST              13      /* stop(pause) at page start?*/
  328. X#define FO              14      /* footer title */
  329. X#define HE              15      /* header title */
  330. X#define M1              16      /* top margin */
  331. X#define M2              17      /* second top margin */
  332. X#define M3              18      /* first bottom margin */
  333. X#define M4              19      /* bottom-most margin       */
  334. X#define IG              20      /* "ignore";comments,Nov 6,82*/
  335. X#define NE              21      /* "need";Nov 7,82*/
  336. X#define FF              22      /* "formfeed";Nov 10*/
  337. X#define SC              23      /* "space character";Nov13*/
  338. X#define TA              25      /* "tabsize";Nov 13*/
  339. X#define EH              26      /* "even headers";Nov 14*/
  340. X#define OH              27      /* "odd headers"*/
  341. X#define EF              28      /* "even footers"*/
  342. X#define OF              29      /* "odd footers"*/
  343. X#define EX              30      /* exit ("abort") */
  344. X#define DB              31      /* "debug"*/
  345. X#define TC              32      /* "translation flag char"*/
  346. X#define TR              33      /* "def translation string"*/
  347. X#define CF              34      /* Dec 4:control flag char*/
  348. X#define IC              35      /* insert character */
  349. X#define AD              37      /* adjust (justify) output lines */
  350. X#define NA              38      /* no adjust of output lines */
  351. X#define WH              39      /* whole line spacing code */
  352. X#define FR              40      /* fractional spacing,code */
  353. X#define DS              41      /* define string*/
  354. X#define DE              42      /* define macro*/
  355. X#define EM              43      /* end macro*/
  356. X#define NR              44      /* register variable*/
  357. X#define DI              45      /* diversion*/
  358. X#define SO              47      /* "source", include*/
  359. X#define PC              48      /* printer control definition*/
  360. X#define TM              49      /* send inline msg to terminal */
  361. X#define BJ              50      /* break with right justification
  362. X                                   of current line */
  363. X#define    PM        51    /* print macro names */
  364. X#define    FT        52    /* set font */
  365. X#define    PO        53    /* page offset */
  366. X#define SS              54      /* show strings */
  367. X#define SR              55      /* show registers */
  368. X
  369. X/****** GLOBAL VARIABLES ********************************/
  370. X
  371. XFILE     *_dobuf, *instream;    /* i/o buffer used for direction  */
  372. Xint     debug;            /* Boolean:  debug mode on/off */
  373. Xint    ro_verbose;        /* Boolean:  verbose mode on/off */
  374. Xint     ro_pagestop;
  375. Xint     ro_adjust;
  376. Xint     ro_useff;
  377. Xint     ro_firstpage, ro_lastpage;    /* for selectively printing output*/
  378. Xint     ro_suppress;        /* if true,no output is passed by putchar()*/
  379. Xint     ro_tival;      /* temporary indent -> default  0 */
  380. Xint     ro_ceval;      /* set equal to number of lines to be centered  */
  381. Xint     ro_spval;      /* blank lines to be spaced down */
  382. Xint     ro_curpag;     /* current output page number; init = 0 */
  383. Xint     ro_newpag;     /* next output page number; init = 1 */
  384. Xint     ro_vlineno;    /* virtual (intended) line advances on page,
  385. X                        see vadv()*/
  386. Xint     ro_vflineno;   /* + line fraction */
  387. Xint     ro_plineno;    /* printer's actual line advances on page,
  388. X                        see padv()*/
  389. Xint     ro_pflineno;   /* + line fraction */
  390. Xint     ro_bottom;     /* end of text area in lines;start of M3+M4 */
  391. Xint     ro_sentence;   /* Nov 20*/
  392. Xint    ro_poval;    /* page offset */
  393. X
  394. X/***    Stack variables
  395. X
  396. X    The following variables are assigned to a stack and when 
  397. X    a new value is assigned, it is "pushed" onto the stack, 
  398. X    and when read, "popped" off.  The stack is read from 
  399. X    the bottom.                          ***/
  400. X
  401. Xint     ro_fill[STKSIZ];       /* set to YES or NO  */
  402. Xint     ro_lsval[STKSIZ];      /* line spacing value -> default will be 1  */
  403. Xint     ro_inval[STKSIZ];      /* left indent -> default  0  */
  404. Xint     ro_rmval[STKSIZ];      /* right margin -> default  PAGEWIDTH  */
  405. Xint     ro_tcval[STKSIZ];      /* translation flag char  */
  406. Xint     ro_plval[STKSIZ];      /* page length in lines  */
  407. Xint     ro_m1val[STKSIZ];      /* margin before& including header in lines */
  408. Xint     ro_m2val[STKSIZ];      /* margin after header in lines */
  409. Xint     ro_m3val[STKSIZ];      /* margin after last text line in lines */
  410. Xint     ro_m4val[STKSIZ];      /* bottom margin, including footer in lines */
  411. Xint     ro_scval[STKSIZ];      /* space character  */
  412. Xint     ro_tabsiz[STKSIZ];     /* spacing of tabstops  */
  413. Xint     ro_cfval[STKSIZ];      /* Dec 4:control flag character value  */
  414. Xint     ro_icval[STKSIZ];      /* insert character */
  415. X
  416. Xchar     ro_curline[ LSZ ];       /*input line buffer, Nov 26 */
  417. Xchar     ro_ehead[ LSZ ], ro_eh2[ LSZ ], ro_eh3[ LSZ ];    /* even header title  */
  418. Xchar     ro_ohead[ LSZ ], ro_oh2[ LSZ ], ro_oh3[ LSZ ];    /* odd header title  */
  419. Xchar     ro_efoot[ LSZ ], ro_ef2[ LSZ ], ro_ef3[ LSZ ];    /* even footer title  */
  420. Xchar     ro_ofoot[ LSZ ], ro_of2[ LSZ ], ro_of3[ LSZ ];    /* even footer title  */
  421. X
  422. Xstruct divfd        /* diversion file descriptor     */
  423. X    {
  424. X    char nm[ 36 ];    /* name  */
  425. X    char fn[ 64 ];    /* name of diversion file (not source file) */
  426. X        int cs;        /* character count  */
  427. X        int ls;        /* line count  */
  428. X    int val;    /* value for register  */
  429. X    char *mstr;    /* pointer to macro character string  */
  430. X    FILE *bf;    /* to instream if open, FALSE otherwise  */
  431. X    struct divfd *prev;
  432. X    };
  433. X
  434. Xchar     tbuf[ TBUFSIZE ];    /* a temporary buffer */
  435. Xint     ro_dir;        /* for "spreading" of lines     */
  436. Xint     ro_outwrds;    /* no. words in ro_outbuf; init = 0  */
  437. Xchar     ro_outbuf[ LSZ ];     /*lines to be filled collected here  */
  438. Xint     ro_outw;       /*current display width of ro_outbuf */
  439. Xint     ro_outpos;     /* =strlen(ro_outbuf)  */
  440. Xint     ro_wtop, ro_ltop, ro_outtop;   /*zero|negative;levels of subscripts */
  441. Xint     ro_wbot, ro_lbot, ro_outbot;   /*zero|positive;levels of subscripts */
  442. Xint     ro_oldln;              /*position of previous main line */
  443. Xint     ro_oldbot;             /*ro_outbot for previous line;reset
  444. X                        each page */
  445. Xint     ro_frq, ro_frval;  /* fractional line?, what fraction size */
  446. Xchar     *ro_frstring; /* ^ to code for fractional spacing */
  447. Xchar     *ro_whstring; /* ^ to code for whole line spacing */
  448. Xchar     *ro_cptr[128-' '];    /*pointer table for print control */
  449. Xchar     *ro_tptr[128-' '];    /*pointer table for translation strings
  450. X                          for char; initialize to null  */
  451. X
  452. Xstruct     divfd *dlink;    /* points to head of diversion list  */
  453. Xstruct     divfd *rlink;    /* points to head of register variable list  */
  454. Xstruct     divfd *slink;    /* points to head of linked string list  */
  455. Xstruct     divfd *mlink;    /* points to head of linked macro list  */
  456. X
  457. X/*following added for buffered and formatted output:   */
  458. X
  459. Xchar     ro_out2buf[LSZ];      /*for line to be output in fancy fmt */
  460. Xint     ro_bpos, ro_cp, ro_pp;         /*buffer,column,printer positions */
  461. Xchar     ro_xbuf[LSZ];         /*strikout buffer */
  462. Xint     ro_xf, ro_xcol;            /* " flag and column  */
  463. Xchar     ro_ubuf[LSZ];         /*underline buffer */
  464. Xint     ro_uf, ro_ucol;            /* " flag and column  */
  465. Xint     ro_first;              /*flag for first pass */
  466. Xchar     ro_dbuf[LSZ];         /*double strike buffer */
  467. Xint     ro_dpos;
  468. Xint     ro_ocnt;
  469. Xint     ro_mcnt;
  470. Xint     ro_blkcnt;
  471. X
  472. Xint     ro_newxf, ro_newuf, ro_newmcnt; /* 3rd Mar,85 ; Conrad Kwok  */
  473. Xchar     ro_lastch;    /* 5th Mar,85  ;  Conrad Kwok  */
  474. X
  475. Xchar     ro_backbuf[BACKSIZE];                 /* Backup buffer  */
  476. Xint     ro_binp;                               /* Position in above;init to 0  */
  477. Xchar     ro_keybd;             /*boolean & prompt for keyboard input */
  478. Xchar     ro_kline[MAXLINE];    /*keyboard line input buffer */
  479. Xchar     *ro_kptr;             /*pointer for above */
  480. X
  481. Xint         ro_fptr;
  482. XFILE     *ro_fstack[FMAX];
  483. Xint    ro_tflag;/*added for start(), complete() */
  484. Xint     ro_xf2, ro_uf2, ro_mcnt2;
  485. X
  486. X/****** DECLARATIONS FOR EXTERNAL FUNCTIONS ************ */
  487. X
  488. X/*      Declarations of externals
  489. X *
  490. X *
  491. X */
  492. X
  493. X#ifndef __STDC__
  494. Xextern  char *malloc();
  495. X#endif
  496. Xextern  char *macq();
  497. Xextern     struct divfd * find2();
  498. Xextern  char ro_getch();
  499. X
  500. X/******** END OF FILE ***********************************/
  501. X
  502. X
  503. ________This_Is_The_END________
  504. if test `wc -l < ro.h` -ne 365; then
  505.     echo 'shar: ro.h was damaged during transit (should have been 365 bytes)'
  506. fi
  507. fi        ; : end of overwriting check
  508. echo 'x - ro.c'
  509. if test -f ro.c; then echo 'shar: not overwriting ro.c'; else
  510. sed 's/^X//' << '________This_Is_The_END________' > ro.c
  511. X/********************************************************/
  512. X/*                            */
  513. X/*    ro.c        main program file for ro    */
  514. X/*                            */
  515. X/*    ro version 1.00                    */
  516. X/*                            */
  517. X/*    Portions copyright (c) 1989 by Ted A. Campbell    */
  518. X/*        Bywater Software            */
  519. X/*        P. O. Box 4023                */
  520. X/*        Duke Station                */
  521. X/*        Durham, NC  27706            */
  522. X/*                            */
  523. X/*    Contains portions of ROFF4, Version 1.60    */
  524. X/*      (c) 1983, 4 by Ernest E. Bergmann               */
  525. X/*        Physics, Building #16            */
  526. X/*        Lehigh University            */
  527. X/*        Bethlehem, Pa. 18015            */
  528. X/*                            */
  529. X/*    Contains portions of ROFF4, Version 1.61    */
  530. X/*      (c) 1985 by Konrad Kwok                         */
  531. X/*        20 3rd Street, Section M        */
  532. X/*        Fariview Park,                */
  533. X/*        Hong Kong                */
  534. X/*                            */
  535. X/*    ro and its predecessor ROFF4 are based on     */
  536. X/*    the ROFF text processor described in Kernigan    */
  537. X/*    and Plauger's now-classic text <Software Tools> */
  538. X/*                            */
  539. X/* Permission is hereby granted for all commercial and    */
  540. X/* non-commercial reproduction and distribution of this */
  541. X/* material provided this notice is included.        */
  542. X/*                            */
  543. X/********************************************************/
  544. X
  545. X#include "ro.h"
  546. X
  547. Xextern  char *ro_gets();
  548. X
  549. Xint ro_iline = 0;
  550. Xint ro_deno = 0;
  551. X
  552. X/*****************MAIN************MAIN*********/
  553. X
  554. Xmain( argc, argv )
  555. X    int argc;
  556. X    char **argv;
  557. X    {
  558. X    register int n;
  559. X    int fs;
  560. X    char option, *pc;
  561. X    char filename[20];
  562. X    struct divfd *pd;
  563. X
  564. X    ro_lastch = NULL;
  565. X    debug = FALSE;
  566. X    ro_verbose = FALSE;
  567. X
  568. X    init_defaults();
  569. X
  570. X    /***    First process any flags         ***/
  571. X
  572. X    for ( n = 1; n < argc; ++n )
  573. X        { 
  574. X        strcpy( filename, argv[ n ] );
  575. X
  576. X        if ( filename[0] == '-' )
  577. X            {
  578. X            option = filename[1];
  579. X            if      ( option == 's' ) ro_pagestop = TRUE;
  580. X            else if ( option == 'o' ) range( &filename[2] );
  581. X            else if ( option == 'f' ) ro_useff = TRUE;
  582. X            else if ( option == 'x' ) 
  583. X                {
  584. X                debug = TRUE;
  585. X                ro_verbose = TRUE;
  586. X                }
  587. X            else if ( option == 'v' ) ro_verbose = TRUE;
  588. X            continue;
  589. X            }
  590. X        }
  591. X
  592. X    if ( ro_verbose == TRUE )
  593. X        {
  594. X        fprintf( stderr, "ro, version 1.00 \n" );
  595. X        }
  596. X
  597. X    if DEBUG
  598. X        {
  599. X        fprintf( stderr, "DEBUG:  initial .ls setting is %d. \n",
  600. X            ro_lsval[0] );
  601. X        }
  602. X
  603. X    /* Now process all files named */
  604. X
  605. X    fs = 0;
  606. X
  607. X    for ( n = 1; n < argc; ++n )
  608. X        { 
  609. X        strcpy( filename, argv[ n ] );
  610. X        if ( filename[0] != '-' )
  611. X            {
  612. X
  613. X            if( pd = find2( filename, dlink ))
  614. X                {
  615. X                dclose( pd );
  616. X                }
  617. X
  618. X            if (( instream = fopen( filename, "r" )) == NULL )
  619. X                {
  620. X                fprintf( stderr, "Can't open <%s> for input.\n", filename );
  621. X                 }
  622. X            else
  623. X                {
  624. X                ++fs;        /* inc. number of files */
  625. X                if ( ro_verbose == TRUE )
  626. X                    {
  627. X                    fprintf( stderr, "Processing <%s>\n", filename );
  628. X                    }
  629. X                dolns();
  630. X                }
  631. X            }
  632. X        }
  633. X
  634. X    /* No files opened; take input from stdin */
  635. X
  636. X    if ( fs == 0 )
  637. X        {
  638. X        if ( ro_verbose && ro_pagestop )
  639. X            {
  640. X            fprintf( stderr, "ERROR:  one cannot use -s (page stop) with standard input. \n" );
  641. X            }
  642. X        ro_pagestop = FALSE;    /* Cannot use page stop if stdin */
  643. X        instream = stdin;
  644. X        dolns();
  645. X        }
  646. X
  647. X    ro_brk();
  648. X    ro_vlineno = ro_plval[ 0 ];
  649. X    padv();
  650. X    if ( ro_useff ) putchar( FORMF );
  651. X    dsclose();                      /* Close all diversions */
  652. X    }                /* end main()         */
  653. X
  654. X/****************************************/
  655. X/* do processing of lines         */
  656. X/****************************************/
  657. X
  658. Xdolns() 
  659. X    {
  660. X    char *pc;
  661. X    struct divfd *sptr;
  662. X    static char name[ 12 ];
  663. X    ro_binp = 0;
  664. X
  665. X    while ( !feof( instream ) | ro_fptr | ro_binp )
  666. X        {
  667. X        ro_gets( ro_curline );
  668. X        ++ro_iline;
  669. X
  670. X        if DEBUG
  671. X            {
  672. X            fprintf( stderr, "DEBUG:  input line # %d <%s> \n",
  673. X                ro_iline, ro_curline );
  674. X            fprintf( stderr, "DEBUG:  ro_curline[0] is <%c> (0x%x)\n", 
  675. X                ro_curline[0], ro_curline[0] );
  676. X            }
  677. X
  678. X        if ( ro_curline[ 0 ] == COMMAND )
  679. X            {
  680. X            name[ 0 ] = ro_curline[ 1 ];
  681. X            if ( class( ro_curline[ 2 ] ) == BLACK )
  682. X                {
  683. X                name[ 1 ] = ro_curline[ 2 ];
  684. X                name[ 2 ] = '\0';
  685. X                }
  686. X            else
  687. X                {
  688. X                name[ 1 ] = '\0';
  689. X                }
  690. X            if ( ( pc = macq( ro_curline )) != NULL )
  691. X                {
  692. X                pbmac( pc, ro_curline );
  693. X                }
  694. X            else if ( ( sptr = find2( name, dlink )) != NULL )
  695. X                {
  696. X                read_div( sptr );
  697. X                }
  698. X            else
  699. X                {
  700. X                command( ro_curline );
  701. X                }
  702. X            }
  703. X        else
  704. X            {
  705. X            text( ro_curline );
  706. X            }
  707. X        if ( feof( instream) )
  708. X            {
  709. X            endso();
  710. X            }
  711. X        }
  712. X    }
  713. X
  714. Xchar *
  715. Xro_gets( line )
  716. X    char *line;
  717. X    {
  718. X    char *l;
  719. X
  720. X    l = line;
  721. X    do
  722. X        {
  723. X        *l = ro_getch();
  724. X        ++l;
  725. X        }
  726. X    while( *(l - 1) != '\n' );
  727. X
  728. X    *( l - 1 ) = '\0';
  729. X
  730. X    if DEBUG
  731. X        {
  732. X        fprintf( stderr, "DEBUG:  ro_gets() <%s> \n", line );
  733. X        }
  734. X
  735. X    return line;
  736. X    }
  737. X
  738. Xchar
  739. Xro_getch()
  740. X    {
  741. X    register int c;
  742. X    static int bflag = FALSE;    /* was last character BACKSLASH? */
  743. X
  744. X    while ( TRUE )
  745. X        {
  746. X        if ( ro_binp == 0 )
  747. X            {
  748. X            if ( feof( instream ))
  749. X                {
  750. X                return '\n';
  751. X                }
  752. X            c = fgetc( instream );
  753. X            }
  754. X        else
  755. X            {
  756. X            c = ro_backbuf[ ro_binp-- ];
  757. X            }
  758. X        switch ( c )
  759. X            {
  760. X            case EOF:
  761. X                bflag = FALSE;
  762. X                return '\n';
  763. X                break;
  764. X            case '\r':
  765. X                bflag = FALSE;
  766. X                break;
  767. X            case BACKSLASH:
  768. X                if ( !bflag )
  769. X                    {
  770. X                    bflag = TRUE;
  771. X                    if ( ro_expand() == PASSBACK )
  772. X                        {
  773. X                        return BACKSLASH;
  774. X                        }
  775. X                    else
  776. X                        {
  777. X                        return ro_getch();
  778. X                        }
  779. X                    }
  780. X                else
  781. X                    {
  782. X                    bflag = FALSE;
  783. X                    return c;
  784. X                    }
  785. X                break;
  786. X            default:
  787. X                bflag = FALSE;
  788. X                return c;
  789. X                break;
  790. X            }
  791. X        }
  792. X    }
  793. X
  794. X/**************************************************************
  795. Xinitializes the global variables governing the execution of the
  796. X format commands.
  797. X**************************************************************/
  798. X
  799. Xinit_defaults()
  800. X    {
  801. X    static time_t now;
  802. X    struct tm *ltime;
  803. X
  804. X    initsk( ro_fill,  FI_DEF);    /* yes we want filled lines */
  805. X    initsk( ro_lsval, LS_DEF);    /* line spacing = 1 */
  806. X    initsk( ro_inval, IN_DEF);    /* left margin indent    0 */
  807. X    initsk( ro_rmval, RM_DEF);    /* right margin = page width    */
  808. X    initsk( ro_tcval, TC_DEF);
  809. X    initsk( ro_plval, PL_DEF);
  810. X    initsk( ro_m1val, M1_DEF);
  811. X    initsk( ro_m2val, M2_DEF);
  812. X    initsk( ro_m3val, M3_DEF);
  813. X    initsk( ro_m4val, M4_DEF);
  814. X    initsk( ro_scval, SC_INI);
  815. X    initsk( ro_tabsiz, TS_DEF);
  816. X    initsk( ro_cfval, CF_DEF);
  817. X    initsk( ro_icval, IC_DEF);
  818. X
  819. X    ro_tival = IN_DEF;     /* left margin temporary indent    0 */
  820. X    ro_ceval = 0;        /* next n lines to be centered - 0 */
  821. X    ro_pagestop = FALSE;
  822. X    ro_useff = FF_INI;
  823. X    ro_firstpage = 1;
  824. X    ro_lastpage = 30000;    /*infinite*/
  825. X    ro_adjust = JU_INI;
  826. X    ro_poval = PO_DEF;
  827. X
  828. X    ro_curpag = 0;
  829. X    ro_newpag = 1;
  830. X    ro_frq = 0;
  831. X    ro_frstring = ro_whstring = NULL;
  832. X    ro_frval = 1;
  833. X    ro_vflineno = ro_pflineno = ro_plineno = 0;
  834. X    ro_vlineno = -1;
  835. X    ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
  836. X    ro_outw = ro_outpos = ro_outtop = ro_outbot = ro_oldln = ro_oldbot = ro_outwrds = 0;
  837. X    ro_outbuf [0] = '\0';
  838. X    ro_dir = 0;
  839. X    ro_eh2[0] = ro_eh3[0] = ro_ehead[0] = '\0';
  840. X    ro_oh2[0] = ro_oh3[0] = ro_ohead[0] = '\0';
  841. X    ro_ef2[0] = ro_ef3[0] = ro_efoot[0] = '\0';
  842. X    ro_of2[0] = ro_of3[0] = ro_ofoot[0] = '\0';
  843. X    memfill( ro_cptr, 2*(128-' '), 0);
  844. X    memfill( ro_tptr, 2*(128-' '), 0);
  845. X
  846. X    ro_out2buf[ 0 ] = ro_bpos = 0;
  847. X    initxu();        /* Initialize overstrike and other variables */
  848. X    ro_mcnt=1;
  849. X    ro_uf = ro_xf = FALSE;
  850. X    memfill( ro_dbuf, LSZ, FALSE);
  851. X    ro_dpos = -1;
  852. X    ro_fptr = 0;             
  853. X    mlink = dlink = rlink = slink = NULL;
  854. X    ro_kptr = ro_kline;
  855. X    *ro_kline=0;
  856. X    ro_keybd=FALSE;
  857. X
  858. X    /***    now set up some pre-defined registers ***/ 
  859. X
  860. X    time( &now );
  861. X    ltime = localtime( &now );
  862. X    preregister( "dy", ltime->tm_mday );
  863. X    preregister( "mo", ltime->tm_mon );
  864. X    preregister( "yr", ltime->tm_year );
  865. X    preregister( "%", ro_curpag );
  866. X    }
  867. X
  868. X/**************************************************************
  869. Xperforms the formatting command returned by comtyp -sets global
  870. X    variables ( indenting, underlining, etc. )
  871. X**************************************************************/
  872. X
  873. Xcommand( line )
  874. X    char *line;
  875. X    {
  876. X    int c_type;    /* command type    */
  877. X    int arg_val;    /* argument value, if any */
  878. X    static int arg_typ;    /* relative (+ or -) or absolute */
  879. X    char wbuf[20], *l;
  880. X    register int i;
  881. X
  882. X    c_type = comtyp (line);
  883. X
  884. X    if DEBUG
  885. X        {
  886. X        fprintf( stderr, "DEBUG:  command is %d \n", c_type );
  887. X        }
  888. X
  889. X    if ( c_type == UNKNOWN )
  890. X        {
  891. X        if ( ro_verbose )
  892. X            fprintf( stderr, "%s: unknown command \n", line);
  893. X        return;
  894. X        }
  895. X    arg_val = get_val( line, &arg_typ );
  896. X
  897. X    if DEBUG
  898. X        {
  899. X        fprintf( stderr, "DEBUG:  get_val returned arg_val = %d, arg_typ = %c\n",
  900. X            arg_val, arg_typ );
  901. X        fprintf( stderr, "DEBUG:  c_type is now %d \n", c_type );
  902. X        }
  903. X
  904. X    switch ( c_type )
  905. X        {
  906. X        case EM :
  907. X        case IG : 
  908. X            break;        /* ignore remark */
  909. X
  910. X        case FI :         /* filled lines    */
  911. X            ro_brk();
  912. X            ro_fill[0] = YES;
  913. X            break;
  914. X
  915. X        case NF:               /* non-filled lines */
  916. X            ro_brk();
  917. X            ro_fill[0] = NO;
  918. X            break;
  919. X
  920. X        case AD :         /* adjusted (justified) lines    */
  921. X            ro_adjust = TRUE;
  922. X            break;
  923. X
  924. X        case NA :        /* non-adjusted lines     */
  925. X            ro_adjust = FALSE;
  926. X            break;
  927. X
  928. X        case BR :         /* just cause a break */
  929. X            ro_brk();
  930. X            break;
  931. X
  932. X        case LS :         /* set line spacing value */
  933. X            setS( ro_lsval, arg_val, arg_typ, LS_DEF, 1, HUGE );
  934. X            break;
  935. X
  936. X        case TI :         /* set temporary left indent */
  937. X            ro_brk();
  938. X            set( &ro_tival, arg_val, arg_typ, TI_DEF, 0, ro_rmval );
  939. X            break;
  940. X
  941. X        case IN :         /* set left indent */
  942. X            setS( ro_inval, arg_val, arg_typ, IN_DEF, 0, ro_rmval-1 );
  943. X            ro_tival = ro_inval[0];
  944. X            break;
  945. X
  946. X        case LL :        /* set line length (right margin) */
  947. X            setS( ro_rmval, arg_val, arg_typ, RM_DEF, ro_tival+1, 256 );
  948. X            break;
  949. X
  950. X        case CE :     /* center next arg_val lines */
  951. X            ro_brk();
  952. X            set( &ro_ceval, arg_val, arg_typ, CE_DEF, 0, HUGE);
  953. X            break;
  954. X
  955. X        case SP :     /* space down arg_val blank lines */
  956. X            set( &ro_spval, arg_val, arg_typ, 1, 0, HUGE);
  957. X            do_space ( ro_spval );
  958. X            break;
  959. X
  960. X        case BP :     /* set pageno arg_val - begin page */
  961. X            ro_brk();
  962. X            if(((ro_vlineno<=0)||(ro_vlineno>=ro_bottom))&&
  963. X                (arg_val==NO_VAL)) 
  964. X                {
  965. X                break;
  966. X                }
  967. X            if ( ro_vlineno > 0 )
  968. X                {
  969. X                do_space (HUGE);
  970. X                }
  971. X            set( &ro_curpag, arg_val, arg_typ, ro_curpag+1, 0, 9999);
  972. X            ro_newpag = ro_curpag;
  973. X            break;
  974. X
  975. X        case NE :     /*"need"*/
  976. X            if ( arg_val == NO_VAL ) 
  977. X                {
  978. X                arg_val = 2;    /*default*/
  979. X                }
  980. X            need( arg_val );
  981. X            break;
  982. X
  983. X        case PL :     /* set page length */
  984. X            setS( ro_plval, arg_val, arg_typ, PL_DEF,
  985. X                ro_m1val[0]+ro_m2val[0]+ro_m3val[0]+ro_m4val[0]+1, HUGE);
  986. X            ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
  987. X            break;
  988. X
  989. X        case TA :     /*tabsize*/
  990. X            setS( ro_tabsiz, arg_val, '0', TS_DEF, 1, HUGE);
  991. X            break;
  992. X
  993. X        case TC :     /* tab character */
  994. X            if ( arg_typ ) 
  995. X                {
  996. X                arg_val=arg_typ;
  997. X                }
  998. X            setS( ro_tcval, arg_val, '0', TC_DEF, BLANK+1, 127);
  999. X            break;
  1000. X
  1001. X        case FT :    /* Set font */
  1002. X            switch( arg_typ )
  1003. X                {
  1004. X                case 'R':
  1005. X                    putback( '\n' );
  1006. X                    putback( ROMAN );
  1007. X                    putback( ESCAPE );
  1008. X                    break;
  1009. X                case 'I':
  1010. X                    putback( '\n' );
  1011. X                    putback( ITALIC );
  1012. X                    putback( ESCAPE );
  1013. X                    break;
  1014. X                case 'B':
  1015. X                    putback( '\n' );
  1016. X                    putback( BOLD );
  1017. X                    putback( ESCAPE );
  1018. X                    break;
  1019. X                default: 
  1020. X                    if ( ro_verbose )
  1021. X                        {
  1022. X                        fprintf( stderr, 
  1023. X                            "ft:  unrecognized font name \"%c\". \n", 
  1024. X                            arg_typ );
  1025. X                        }
  1026. X                }
  1027. X            break;
  1028. X
  1029. X        case TR :     /*translation string defined here*/
  1030. X            gettr(); 
  1031. X            break;
  1032. X
  1033. X        case DS :     /*define string*/
  1034. X            insert(); 
  1035. X            break;
  1036. X
  1037. X        case DE :     /*define macro*/
  1038. X            ++ro_deno;
  1039. X            if DEBUG
  1040. X                {
  1041. X                fprintf( stderr, "DEBUG:  .de number %d \n",
  1042. X                    ro_deno );
  1043. X                }
  1044. X            minsert();
  1045. X            break;
  1046. X
  1047. X        case NR :        /*register variable*/
  1048. X            dovar(); 
  1049. X            break;
  1050. X
  1051. X        case DI :     /*diversion to file*/
  1052. X            dodiv(); 
  1053. X            break;
  1054. X
  1055. X        case SO :     /*source from file*/
  1056. X            source(); 
  1057. X            break;
  1058. X
  1059. X        case PM :    /* print macro definitions */
  1060. X            showm();
  1061. X            break;
  1062. X
  1063. X        case PO :    /* page offset */
  1064. X            set( &ro_poval, arg_val, arg_typ, 1, 0, HUGE );
  1065. X            break;
  1066. X
  1067. X        case TM :     /* send message to terminal */
  1068. X            getwrd(ro_curline, wbuf);    /*skip command*/
  1069. X            skip_blanks(ro_curline);
  1070. X            trunc_bl(ro_curline);
  1071. X            fprintf( stderr, "<%s>\n", ro_curline);
  1072. X            break;
  1073. X
  1074. X#ifdef    NONROFF
  1075. X
  1076. X        case M1:        /* set topmost margin */
  1077. X            setS( ro_m1val, arg_val, arg_typ, M1_DEF, 0, HUGE);
  1078. X            break;
  1079. X
  1080. X        case M2:        /* set second top margin */
  1081. X            setS( ro_m2val, arg_val, arg_typ, M2_DEF, 0, HUGE);
  1082. X            break;
  1083. X
  1084. X        case M3:        /* set first bottom margin */
  1085. X            setS( ro_m3val, arg_val, arg_typ, M3_DEF, 0, HUGE);
  1086. X            ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
  1087. X            break;
  1088. X
  1089. X        case M4:        /* set bottom-most margin */
  1090. X            setS( ro_m4val, arg_val, arg_typ, M4_DEF, 0, HUGE);
  1091. X            ro_bottom = ro_plval[0] - ro_m3val[0] - ro_m4val[0];
  1092. X            break;
  1093. X
  1094. X        case HE :     /* get header title for pages */
  1095. X            gettl3 ( line, ro_ehead, ro_eh2, ro_eh3 );
  1096. X            gettl3 ( line, ro_ohead, ro_oh2, ro_oh3 );
  1097. X            break;
  1098. X
  1099. X        case OH :     /*get odd header title*/
  1100. X            gettl3 ( line, ro_ohead, ro_oh2, ro_oh3 );
  1101. X            break;
  1102. X
  1103. X        case EH :     /*get even header title*/
  1104. X            gettl3 ( line, ro_ehead, ro_eh2, ro_eh3 );
  1105. X            break;
  1106. X
  1107. X        case FO :     /* get footer title for pages */
  1108. X            gettl3 ( line, ro_efoot, ro_ef2, ro_ef3 );
  1109. X            gettl3 ( line, ro_ofoot, ro_of2, ro_of3 );
  1110. X            break;
  1111. X
  1112. X        case OF :     /* get odd page footer title*/
  1113. X            gettl3 ( line, ro_ofoot, ro_of2, ro_of3 );
  1114. X            break;
  1115. X
  1116. X        case EF :     /* get even page footer title*/
  1117. X            gettl3 ( line, ro_efoot, ro_ef2, ro_ef3 );
  1118. X            break;
  1119. X
  1120. X        case ST :     /* stop(pause) at each page?*/
  1121. X            set( &ro_pagestop, arg_val, '0', YES, NO, YES);
  1122. X            break;
  1123. X
  1124. X        case BJ :     /*break with right justification*/
  1125. X            if(ro_fill)/*not applicable otherwise*/
  1126. X                {
  1127. X                spread(ro_outbuf,
  1128. X                ro_min(ro_rmval-ro_tival, MAXLINE-1)-ro_outw+1,
  1129. X                ro_outwrds);
  1130. X                ro_brk();
  1131. X                }
  1132. X            break;
  1133. X
  1134. X        case FF :     /*formfeed*/
  1135. X            set( &ro_useff, arg_val, '0', FF_DEF, NO, YES);
  1136. X            break;
  1137. X
  1138. X        case SC :     /*space character*/
  1139. X            if ( arg_typ ) 
  1140. X                {
  1141. X                arg_val=arg_typ;
  1142. X                }
  1143. X            setS( ro_scval, arg_val, '0', SC_INI, BLANK, 127);
  1144. X            break;
  1145. X
  1146. X        case EX :     /* exit (abort) */
  1147. X            if ( ro_verbose )
  1148. X                fprintf( stderr, ".ex:  user abort.  \n");
  1149. X            exit(-1);         /* tac */
  1150. X
  1151. X        case CF :     /*translate character flag*/
  1152. X            if ( arg_typ ) 
  1153. X                {
  1154. X                arg_val=arg_typ;
  1155. X                }
  1156. X            setS( ro_cfval, arg_val, '0', CF_DEF, BLANK+1, 127);
  1157. X            break;
  1158. X
  1159. X        case IC :     /* insert character for macro replace */
  1160. X            if ( arg_typ ) 
  1161. X                {
  1162. X                arg_val = arg_typ;
  1163. X                }
  1164. X            setS( ro_icval, arg_val, '0', IC_DEF, BLANK+1, 127 );
  1165. X            break;
  1166. X
  1167. X        case SR :       /* print register definitions */
  1168. X            showr();
  1169. X            break;
  1170. X
  1171. X        case SS :       /* print string definitions */
  1172. X            showit();
  1173. X            break;
  1174. X
  1175. X        case DB :     /* debug */
  1176. X            set( &debug, arg_val, '0', NO, NO, YES);
  1177. X            if DEBUG 
  1178. X                {
  1179. X                fprintf( stderr, "Debug on...\n");
  1180. X                }
  1181. X            else 
  1182. X                {
  1183. X                fprintf( stderr, "...end of debug. \n");
  1184. X                }
  1185. X            break;
  1186. X#endif
  1187. X
  1188. X        default :
  1189. X            if ( ro_verbose )
  1190. X                {
  1191. X                fprintf( stderr, "Command %d not found.\n", c_type );
  1192. X                fprintf( stderr, "        line: <%s> \n", line );
  1193. X                }
  1194. X            break;
  1195. X        }
  1196. X    }
  1197. X
  1198. Xrange( s )
  1199. X    char *s;
  1200. X    { 
  1201. X    int num;
  1202. X    num=0;
  1203. X    while(isdigit(*s)) num=num*10+(*(s++)-'0');
  1204. X    if(num) ro_firstpage=num;
  1205. X    if(*s=='-')
  1206. X        {
  1207. X        s++; 
  1208. X        num=0;
  1209. X        while(isdigit(*s)) num=num*10+(*(s++)-'0');
  1210. X        if(num) ro_lastpage=num;
  1211. X        }
  1212. X    else    ro_lastpage = ro_firstpage;
  1213. X    }
  1214. X
  1215. Xro_min( n1, n2 )
  1216. X    int n1, n2;
  1217. X    {
  1218. X    if ( n1 > n2 )
  1219. X        {
  1220. X        return n2;
  1221. X        }
  1222. X    else
  1223. X        {
  1224. X        return n1;
  1225. X        }
  1226. X    }
  1227. X
  1228. Xro_max( n1, n2 )
  1229. X    int n1, n2;
  1230. X    {
  1231. X    if ( n1 < n2 )
  1232. X        {
  1233. X        return n2;
  1234. X        }
  1235. X    else
  1236. X        {
  1237. X        return n1;
  1238. X        }
  1239. X    }
  1240. X
  1241. Xmemfill( b, n, c )
  1242. X    char *b;
  1243. X    int n;
  1244. X    char c;
  1245. X    {
  1246. X    register int x;
  1247. X    char *y;
  1248. X
  1249. X    y = b;
  1250. X    for ( x = 0; x < n; ++x )
  1251. X        {
  1252. X        *y = c;
  1253. X        }
  1254. X    }
  1255. X
  1256. ________This_Is_The_END________
  1257. if test `wc -l < ro.c` -ne 745; then
  1258.     echo 'shar: ro.c was damaged during transit (should have been 745 bytes)'
  1259. fi
  1260. fi        ; : end of overwriting check
  1261. echo 'x - ro_proc.c'
  1262. if test -f ro_proc.c; then echo 'shar: not overwriting ro_proc.c'; else
  1263. sed 's/^X//' << '________This_Is_The_END________' > ro_proc.c
  1264. X/********************************************************/
  1265. X/*                            */
  1266. X/*    ro_proc.c    various procedures for ro    */
  1267. X/*                            */
  1268. X/*    ro version 1.00                    */
  1269. X/*                            */
  1270. X/*    Portions copyright (c) 1989 by Ted A. Campbell    */
  1271. X/*        Bywater Software            */
  1272. X/*        P. O. Box 4023                */
  1273. X/*        Duke Station                */
  1274. X/*        Durham, NC    27706            */
  1275. X/*                            */
  1276. X/*    Contains portions of ROFF4, Version 1.60    */
  1277. X/*    (c) 1983, 4 by Ernest E. Bergmann        */
  1278. X/*        Physics, Building #16            */
  1279. X/*        Lehigh University            */
  1280. X/*        Bethlehem, Pa. 18015            */
  1281. X/*                            */
  1282. X/*    Contains portions of ROFF4, Version 1.61    */
  1283. X/*    (c) 1985 by Konrad Kwok                */
  1284. X/*        20 3rd Street, Section M        */
  1285. X/*        Fariview Park,                */
  1286. X/*        Hong Kong                */
  1287. X/*                            */
  1288. X/*    ro and its predecessor ROFF4 are based on     */
  1289. X/*    the ROFF text processor described in Kernigan    */
  1290. X/*    and Plauger's now-classic text <Software Tools> */
  1291. X/*                            */
  1292. X/* Permission is hereby granted for all commercial and    */
  1293. X/* non-commercial reproduction and distribution of this */
  1294. X/* material provided this notice is included.        */
  1295. X/*                            */
  1296. X/********************************************************/
  1297. X
  1298. X#include "ro.h"
  1299. X
  1300. X/**********************************************************
  1301. XRemoves white-space characters at start of string.
  1302. X***********************************************************/
  1303. X
  1304. Xskip_blanks ( string )
  1305. X    char *string;     /* cursor to original string */
  1306. X    {
  1307. X    char *p;     /* cursor to 'final' string */
  1308. X    for(p=string;*string==BLANK||*string==TAB||*string==NEWLINE;
  1309. X        string++);
  1310. X        while(*(p++) = *(string++));
  1311. X    }
  1312. X
  1313. X/*************************************************************/
  1314. X
  1315. Xint comtyp (line)
  1316. X    char *line;
  1317. X    {
  1318. X    char let1, let2;
  1319. X    let1 = line[1];
  1320. X    let2 = line[2];
  1321. X
  1322. X    if ( let1==COMMAND )        return( EM ); /* end macro or comment */
  1323. X    if ( let1=='f' && let2=='i')    return( FI ); /* fill              */
  1324. X    if ( let1=='t' && let2=='i')    return( TI ); /* temp. left indent    */
  1325. X    if ( let1=='b' && let2=='p')    return( BP ); /* break, page #          */
  1326. X    if ( let1=='b' && let2=='r')    return( BR ); /* break              */
  1327. X    if ( let1=='c' && let2=='e')    return( CE ); /* center line(s)          */
  1328. X    if ( let1=='i' && let2=='n')    return( IN ); /* left indent          */
  1329. X    if ( let1=='l' && let2=='l')    return( LL ); /* right margin          */
  1330. X    if ( let1=='l' && let2=='s')    return( LS ); /* line spacing          */
  1331. X    if ( let1=='n' && let2=='f')    return( NF ); /* no fill          */
  1332. X    if ( let1=='p' && let2=='l')    return( PL ); /* page length          */
  1333. X    if ( let1=='s' && let2=='p')    return( SP ); /* output blank lines   */
  1334. X    if ( let1=='n' && let2=='e')    return( NE ); /* need vertical spaces */
  1335. X    if ( let1=='t' && let2=='a')    return( TA ); /* tab size          */
  1336. X    if ( let1=='t' && let2=='c')    return( TC ); /* tab character          */
  1337. X    if ( let1=='t' && let2=='r')    return( TR ); /* translate chars      */
  1338. X    if ( let1=='a' && let2=='d')    return( AD ); /* adjust output lines  */
  1339. X    if ( let1=='n' && let2=='a')    return( NA ); /* no adjust output     */
  1340. X    if ( let1=='e' && let2=='m')    return( EM ); /* end macro          */
  1341. X    if ( let1=='d' && let2=='e')    return( DE ); /* define macro          */
  1342. X    if ( let1=='d' && let2=='s')    return( DS ); /* define string          */
  1343. X    if ( let1=='n' && let2=='r')    return( NR ); /* number register      */
  1344. X    if ( let1=='d' && let2=='i')    return( DI ); /* divert output          */
  1345. X    if ( let1=='s' && let2=='o')    return( SO ); /* source from file     */
  1346. X    if ( let1=='p' && let2=='m')    return( PM ); /* print macros         */
  1347. X    if ( let1=='e' && let2=='x')    return( EX ); /* exit (abort)          */
  1348. X    if ( let1=='i' && let2=='g')    return( IG ); /* ignore -- comment    */
  1349. X    if ( let1=='t' && let2=='m')    return( TM ); /* message to terminal  */
  1350. X    if ( let1=='f' && let2=='t')    return( FT ); /* set font          */
  1351. X    if ( let1=='p' && let2=='o')    return( PO ); /* page offset           */
  1352. X
  1353. X#ifdef    NOTYET
  1354. X    if ( let1=='w' && let2=='h')    return( WH ); /* set trap           */
  1355. X#endif
  1356. X
  1357. X#ifdef    NONROFF
  1358. X    if ( let1=='F' && let2=='O')    return( FO ); /* footer for title     */
  1359. X    if ( let1=='H' && let2=='E')    return( HE ); /* header for title     */
  1360. X    if ( let1=='S' && let2=='T')    return( ST ); /* stop between pages   */
  1361. X    if ( let1=='F' && let2=='F')    return( FF ); /* form feed          */
  1362. X    if ( let1=='S' && let2=='C')    return( SC ); /* space character      */
  1363. X    if ( let1=='O' && let2=='H')    return( OH ); /* odd-page header      */
  1364. X    if ( let1=='O' && let2=='F')    return( OF ); /* odd-page footer      */
  1365. X    if ( let1=='E' && let2=='H')    return( EH ); /* even-page header     */
  1366. X    if ( let1=='E' && let2=='F')    return( EF ); /* even-page footer     */
  1367. X    if ( let1=='C' && let2=='F')    return( CF ); /* trans. char. flag    */
  1368. X    if ( let1=='I' && let2=='C')    return( IC ); /* insert character     */
  1369. X    if ( let1=='B' && let2=='J')    return( BJ ); /* break, justified     */
  1370. X    if ( let1=='S' && let2=='S')    return( SS ); /* show strings */
  1371. X    if ( let1=='S' && let2=='R')    return( SR ); /* show registers    */
  1372. X    if ( let1=='M')
  1373. X        { 
  1374. X        if (let2=='1')        return( M1 );
  1375. X        if (let2=='2')        return( M2 );
  1376. X        if (let2=='3')        return( M3 );
  1377. X        if (let2=='4')        return( M4 );
  1378. X        }
  1379. X    if ( let1=='D' && let2=='B')    return( DB ); /* debug on             */
  1380. X#endif
  1381. X
  1382. X    return( UNKNOWN );            /* no match */
  1383. X    }
  1384. X
  1385. X/*************************************************************
  1386. Xgets the number ( if any ) associated with any command 
  1387. X*************************************************************/
  1388. X
  1389. Xget_val( line, typ )
  1390. X    char *line;
  1391. X    int *typ;
  1392. X    {
  1393. X    int i;
  1394. X    char local[ MAXLINE ];
  1395. X    strcpy (local, line);     /* local copy */
  1396. X
  1397. X    /* skip over the command line */
  1398. X    for(i=1; local[i]!=' '&&local[i]!='\t'&&local[i]!='\n'
  1399. X        &&local[i]!=0; i++);
  1400. X
  1401. X    skip_blanks (&local[i]);        /* find the number */
  1402. X    *typ = local[i];        /* relative or absolute */
  1403. X    if ( *typ=='+' || *typ=='-' )
  1404. X        {
  1405. X        i++;
  1406. X        }
  1407. X    else if ( !isdigit( *typ ) )
  1408. X        {
  1409. X        return( NO_VAL );
  1410. X        }
  1411. X    return ( atoi( &local[i] ));
  1412. X    }
  1413. X
  1414. X/*************************************************************
  1415. X sets a non-stacked global parameter like ro_spval, ro_pagestop, etc.
  1416. X Also checks that the new value is within the range of that 
  1417. X parameter.    Assigns the default for that parameter if no value
  1418. X is specified.
  1419. X*************************************************************/
  1420. X
  1421. Xset( param, val, arg_typ, defval, minval, maxval )
  1422. X    int *param, val, defval, minval, maxval;
  1423. X    int arg_typ;
  1424. X    {
  1425. X    if ( val == NO_VAL ) 
  1426. X        {
  1427. X        *param = defval;     /* defaulted */
  1428. X        }
  1429. X    else if (arg_typ == '+') 
  1430. X        {
  1431. X        *param += val;    /* relative + */
  1432. X        }
  1433. X    else if ( arg_typ == '-' ) 
  1434. X        {
  1435. X        *param -= val;    /* relative - */
  1436. X        }
  1437. X    else    
  1438. X        {
  1439. X        *param = val;             /* absolute */
  1440. X        }
  1441. X    *param = ro_min (*param, maxval);
  1442. X    *param = ro_max (*param, minval);
  1443. X
  1444. X    if DEBUG fprintf( stderr,"DEBUG:  set() *param = %d\n", *param);
  1445. X    }
  1446. X
  1447. X/*************************************************************
  1448. X        end current filled line 
  1449. X**************************************************************/
  1450. X
  1451. Xro_brk()
  1452. X    {
  1453. X    int l;
  1454. X    if DEBUG 
  1455. X        {
  1456. X        fprintf( stderr,"DEBUG:  ro_brk(): ro_outbuf=<%s>\n", ro_outbuf);
  1457. X        }
  1458. X
  1459. X    if (ro_outpos)
  1460. X        {
  1461. X        put( ro_outbuf );
  1462. X        }
  1463. X    ro_outw = ro_outpos = ro_outtop = ro_outbot = ro_outwrds = 0;
  1464. X    ro_outbuf[0] = '\0';
  1465. X    }
  1466. X
  1467. X/**************************************************/
  1468. X
  1469. Xinitxu()        /*initialize underline,overstrike variables*/
  1470. X    {     
  1471. X    ro_xcol = ro_ucol = -1;
  1472. X    memfill(ro_xbuf,LSZ,' ');
  1473. X    memfill(ro_ubuf,LSZ,' ');
  1474. X    }
  1475. X
  1476. X/****************************************/
  1477. X
  1478. Xneed(n) /*test for space before footer*/
  1479. X    int n;    /*whole lines*/
  1480. X    {
  1481. X    if (( ro_vlineno >= (ro_bottom-n) ) && ( ro_bottom >= ro_vlineno ) )
  1482. X        {
  1483. X        do_space( HUGE );
  1484. X        ro_newpag = ++ro_curpag;
  1485. X        }
  1486. X    }
  1487. X
  1488. ________This_Is_The_END________
  1489. if test `wc -l < ro_proc.c` -ne 224; then
  1490.     echo 'shar: ro_proc.c was damaged during transit (should have been 224 bytes)'
  1491. fi
  1492. fi        ; : end of overwriting check
  1493. echo 'x - ro_macr.c'
  1494. if test -f ro_macr.c; then echo 'shar: not overwriting ro_macr.c'; else
  1495. sed 's/^X//' << '________This_Is_The_END________' > ro_macr.c
  1496. X/********************************************************/
  1497. X/*                            */
  1498. X/*    ro_macr.c    macro and diversion routines    */
  1499. X/*            for ro                */
  1500. X/*                            */
  1501. X/*    ro version 1.00                    */
  1502. X/*                            */
  1503. X/*    Portions copyright (c) 1989 by Ted A. Campbell    */
  1504. X/*        Bywater Software            */
  1505. X/*        P. O. Box 4023                */
  1506. X/*        Duke Station                */
  1507. X/*        Durham, NC  27706            */
  1508. X/*                            */
  1509. X/*    Contains portions of ROFF4, Version 1.60    */
  1510. X/*      (c) 1983, 4 by Ernest E. Bergmann               */
  1511. X/*        Physics, Building #16            */
  1512. X/*        Lehigh University            */
  1513. X/*        Bethlehem, Pa. 18015            */
  1514. X/*                            */
  1515. X/*    Contains portions of ROFF4, Version 1.61    */
  1516. X/*      (c) 1985 by Konrad Kwok                         */
  1517. X/*        20 3rd Street, Section M        */
  1518. X/*        Fariview Park,                */
  1519. X/*        Hong Kong                */
  1520. X/*                            */
  1521. X/*    ro and its predecessor ROFF4 are based on     */
  1522. X/*    the ROFF text processor described in Kernigan    */
  1523. X/*    and Plauger's now-classic text <Software Tools> */
  1524. X/*                            */
  1525. X/* Permission is hereby granted for all commercial and    */
  1526. X/* non-commercial reproduction and distribution of this */
  1527. X/* material provided this notice is included.        */
  1528. X/*                            */
  1529. X/********************************************************/
  1530. X
  1531. X#include "ro.h"
  1532. X
  1533. X/********************************************/
  1534. X/* insert()  -- process .ds command        */
  1535. X/* takes a command line in ro_curline and adds its
  1536. Xentry to the table */
  1537. X
  1538. Xinsert()
  1539. X    {
  1540. X    static char name[ LSZ ];
  1541. X    register int n;
  1542. X    char c, *l;
  1543. X    struct divfd *sptr;
  1544. X
  1545. X     /*pass over command*/
  1546. X
  1547. X     l = ro_curline;
  1548. X     for ( c = *l; c != ' ' && c != '\n' && c != '\t'; l++ )
  1549. X        {
  1550. X        c = *l;
  1551. X        }
  1552. X
  1553. X     /*advance to first non-blank */
  1554. X
  1555. X     for ( ; c == ' ' || c == '\t'; l++ )
  1556. X        {
  1557. X        c = *l;
  1558. X        }
  1559. X     if ( c == '\n' )
  1560. X        {
  1561. X        if ( ro_verbose == TRUE )
  1562. X            {
  1563. X            fprintf( stderr, ".ds:  no arguments \n" );
  1564. X            }
  1565. X        return -1;
  1566. X        }
  1567. X
  1568. X    /* get the name of the macro into the buffer */
  1569. X
  1570. X    n = 0;
  1571. X    --l;
  1572. X    do
  1573. X        {
  1574. X        name[ n ] = *l;
  1575. X        ++l;
  1576. X        ++n;
  1577. X        }
  1578. X    while( *l != ' ' && *l != '\t' && *l != '\n' );
  1579. X    name[ n ] = '\0';        /* terminate name with \0 */
  1580. X
  1581. X    if ( strlen( name ) > 2 ) 
  1582. X        {
  1583. X        name[ 2 ] = '\0';
  1584. X        if ( ro_verbose == TRUE )
  1585. X            {
  1586. X            fprintf( stderr, ".ds:  string name over two characters, shortened to <%s>. \n", 
  1587. X                name );
  1588. X            }
  1589. X        }
  1590. X
  1591. X      /*advance to first non-blank */
  1592. X
  1593. X     c = *l;
  1594. X     for ( ; c == ' ' || c == '\t'; l++ )
  1595. X        {
  1596. X        c = *l;
  1597. X        }
  1598. X     if ( c == '\n' )
  1599. X        {
  1600. X        if ( ro_verbose == TRUE )
  1601. X            {
  1602. X            fprintf( stderr, ".ds:  no string argument \n" );
  1603. X            }
  1604. X        return -1;
  1605. X        }
  1606. X
  1607. X    /* now get the string itself into the tbuf buffer */
  1608. X
  1609. X    if ( c == '\"' )
  1610. X        {
  1611. X        n = 0;
  1612. X        do
  1613. X            {
  1614. X            tbuf[ n ] = *l;
  1615. X            ++l;
  1616. X            ++n;
  1617. X            }
  1618. X        while( *l != c );
  1619. X        tbuf[ n ] = '\0';        /* terminate name with \0 */
  1620. X        }
  1621. X    else
  1622. X        {
  1623. X        n = 0;
  1624. X        do
  1625. X            {
  1626. X            tbuf[ n ] = *l;
  1627. X            ++l;
  1628. X            ++n;
  1629. X            }
  1630. X        while( *l != ' ' && *l != '\t' && *l != '\n' );
  1631. X        tbuf[ n ] = '\0';        /* terminate name with \0 */
  1632. X        }
  1633. X
  1634. X    /* see if it is already defined      */
  1635. X
  1636. X    if( ( sptr = find2( name, slink )) != NULL )    
  1637. X        {
  1638. X        if ( ro_verbose == TRUE )
  1639. X            {
  1640. X            fprintf( stderr, "%cWarning: <%s> was defined to be <%s>\n",
  1641. X                BELL, name, sptr->mstr );
  1642. X            fprintf( stderr, "...now it is defined to be <%s>\n", tbuf );
  1643. X            }
  1644. X        }
  1645. X
  1646. X    else 
  1647. X        {
  1648. X        if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
  1649. X            {
  1650. X            fprintf( stderr, "Fatal error: cannot allocate memory for insertion structure.  \n" ); 
  1651. X            exit ( -1 );
  1652. X            }
  1653. X
  1654. X        /* allocation succeeded, set up links */
  1655. X
  1656. X        sptr->prev = slink;        /* save previous link    */
  1657. X        slink = sptr;            /* reset link        */
  1658. X        strcpy( sptr->nm, name );
  1659. X        sptr->mstr = NULL;
  1660. X        }
  1661. X
  1662. X    /* allocate memory for the new string if it is longer 
  1663. X       than the current string */ 
  1664. X
  1665. X    if ( strlen( tbuf ) > strlen( sptr->mstr ) )
  1666. X        {
  1667. X        if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
  1668. X            {
  1669. X            fprintf( stderr, "Fatal error:  failed to allocate memory for string. \n" );
  1670. X            exit( -1 );
  1671. X            }
  1672. X        }
  1673. X
  1674. X    /* copy the string to the new memory */
  1675. X
  1676. X    strcpy( sptr->mstr, tbuf );
  1677. X
  1678. X    }
  1679. X
  1680. X/****************************************/
  1681. X
  1682. Xshowit()        /* displays the list of entries in the string
  1683. X            substitution table pointed to by HEAD. */
  1684. X    {
  1685. X    struct divfd *pw;
  1686. X    fprintf( stderr, "Strings defined:\n");
  1687. X    dashes();
  1688. X    pw = slink;
  1689. X    while( pw != NULL )
  1690. X        {
  1691. X        fprintf( stderr, "%s:\t<%s> \n", pw->nm, pw->mstr );
  1692. X        pw = pw->prev;
  1693. X        }
  1694. X    dashes();
  1695. X    }
  1696. X
  1697. X/****************************************/
  1698. X
  1699. Xputback( c )    /*cf K & P, p256*/
  1700. X    char c;
  1701. X    {
  1702. X    if ( ++ro_binp >= BACKSIZE )
  1703. X        {
  1704. X        fprintf( stderr, "Fatal error:  too many characters pushed back\n");
  1705. X        exit( -1 );
  1706. X        }
  1707. X    ro_backbuf[ ro_binp ] = c;
  1708. X    }
  1709. X
  1710. X/** add by Conrad Kwok. 9th Sept.,84 ****/
  1711. X
  1712. Xpbmac( s, sl )            /* s = pointer to macro text     */
  1713. X    char s[], sl[];        /* sl = current line         */
  1714. X    {
  1715. X    static char *parms[10], dupln[LSZ];
  1716. X    register int i;
  1717. X
  1718. X    strcpy( dupln, sl );        /* get a copy of the current line */
  1719. X    setparm( dupln, parms );
  1720. X    for ( i = strlen(s)-1; i >= 0; )
  1721. X        {
  1722. X        if ( isdigit( s[i] ))
  1723. X            {
  1724. X            if ( i > 0 && s[ i - 1 ] == '$' )
  1725. X                { 
  1726. X                pbstr( parms[ s[i--] & 0x0f ]); 
  1727. X                --i;
  1728. X                }
  1729. X            else
  1730. X                {
  1731. X                putback( s[i--] );
  1732. X                }
  1733. X            }
  1734. X        else
  1735. X            {
  1736. X            putback( s[i--] );
  1737. X            }
  1738. X        }
  1739. X    }
  1740. X
  1741. Xsetparm( sl, parms)
  1742. X    char *sl, *parms[];
  1743. X    { 
  1744. X    char a,c;
  1745. X    int nuparm;
  1746. X    for ( c = *sl; c != ' ' && c != '\n' && c != '\t'; )
  1747. X        {
  1748. X        c = *++sl;
  1749. X        }
  1750. X
  1751. X    while ( c == ' ' || c == '\t' )
  1752. X        {
  1753. X        c = *++sl;
  1754. X        }
  1755. X
  1756. X    for ( nuparm = 0; nuparm < 10; ) 
  1757. X        {
  1758. X        if (!(isalnum(c) || (c=='+') || (c=='-')))
  1759. X            {
  1760. X            sl++;
  1761. X            }
  1762. X        else
  1763. X            {
  1764. X            c = ' ';
  1765. X            }
  1766. X        parms[ nuparm++ ] = sl;
  1767. X
  1768. X        for ( a = *sl; a != c && a != '\n' && a != '\0'; )
  1769. X            {
  1770. X            if ( c == ' ' && a == '\t' ) 
  1771. X                {
  1772. X                break;
  1773. X                }
  1774. X
  1775. X            else 
  1776. X                {
  1777. X                a = *++sl;
  1778. X                }
  1779. X            }
  1780. X        *sl = '\0';
  1781. X        c = a;
  1782. X        if ( a != '\0' && a != '\n') 
  1783. X            {
  1784. X            while ( c == ' ' || c == '\t') 
  1785. X                {
  1786. X                c = *++sl;
  1787. X                }
  1788. X            }
  1789. X        }
  1790. X    }
  1791. X
  1792. X/****************************************/
  1793. X
  1794. Xpbstr( s )        /*put back string on input; cf K&P,p257*/
  1795. X    char s[LSZ];
  1796. X    {
  1797. X    int i;
  1798. X    for ( i = strlen(s); i > 0; ) 
  1799. X        {
  1800. X        putback( s[--i] );
  1801. X        }
  1802. X    }
  1803. X
  1804. Xro_expand()
  1805. X    {
  1806. X    char c, d, name[ 36 ];
  1807. X    register int n;
  1808. X    struct divfd *sptr;
  1809. X
  1810. X    c = ro_getch();
  1811. X    switch( c )
  1812. X        {
  1813. X        case BACKSLASH:
  1814. X            return PASSBACK;
  1815. X            break;
  1816. X        case '*':        /* expand defined string */
  1817. X            d = ro_getch();
  1818. X            if ( d == '(' )    /* two-letter name */
  1819. X                {
  1820. X                name[ 0 ] = ro_getch();
  1821. X                name[ 1 ] = ro_getch();
  1822. X                name[ 2 ] = '\0';
  1823. X                }
  1824. X            else        /* one-character name */
  1825. X                {
  1826. X                name[ 0 ] = d;
  1827. X                name[ 1 ] = '\0';
  1828. X                }
  1829. X            if ( ( sptr = find2( name, slink )) == NULL )
  1830. X                {
  1831. X                if ( ro_verbose == TRUE )
  1832. X                    {
  1833. X                    fprintf( stderr, "ro:  failed to find string name <%s> \n", 
  1834. X                        name );
  1835. X                    }
  1836. X                }
  1837. X            else
  1838. X                {
  1839. X                n = strlen( sptr->mstr ) - 1;
  1840. X                while( n >= 0 )
  1841. X                    {
  1842. X                    putback( sptr->mstr[ n ] );
  1843. X                    --n;
  1844. X                    }
  1845. X                }
  1846. X            break;
  1847. X        case 'n':        /* expand number register */
  1848. X            d = ro_getch();
  1849. X            if ( d == '(' )    /* two-letter name */
  1850. X                {
  1851. X                name[ 0 ] = ro_getch();
  1852. X                name[ 1 ] = ro_getch();
  1853. X                name[ 2 ] = '\0';
  1854. X                }
  1855. X            else        /* one-character name */
  1856. X                {
  1857. X                name[ 0 ] = d;
  1858. X                name[ 1 ] = '\0';
  1859. X                }
  1860. X            if ( ( sptr = find2( name, rlink )) == NULL )
  1861. X                {
  1862. X                if ( ro_verbose == TRUE )
  1863. X                    {
  1864. X                    fprintf( stderr, "ro:  failed to find register name <%s> \n", 
  1865. X                        name );
  1866. X                    }
  1867. X                }
  1868. X            else
  1869. X                {
  1870. X                sprintf( tbuf, "%d", sptr->val );
  1871. X                n = strlen( tbuf ) - 1;
  1872. X                while( n >= 0 )
  1873. X                    {
  1874. X                    putback( tbuf[ n ] );
  1875. X                    --n;
  1876. X                    }
  1877. X                }
  1878. X            break;
  1879. X        case 'u':        /* Half-line up */
  1880. X            putback( HALFUP );
  1881. X            putback( ESCAPE );
  1882. X            break;
  1883. X        case 'd':        /* Half-line down */
  1884. X            putback( HALFDOWN );
  1885. X            putback( ESCAPE );
  1886. X            break;
  1887. X        case 'f':        /* switch font */
  1888. X            d = ro_getch();
  1889. X            switch( d )
  1890. X                {
  1891. X                case 'R':
  1892. X                    putback( ROMAN );
  1893. X                    putback( ESCAPE );
  1894. X                    break;
  1895. X                case 'I':
  1896. X                    putback( ITALIC );
  1897. X                    putback( ESCAPE );
  1898. X                    break;
  1899. X                case 'B':
  1900. X                    putback( BOLD );
  1901. X                    putback( ESCAPE );
  1902. X                    break;
  1903. X                default: 
  1904. X                    if ( ro_verbose == TRUE )
  1905. X                        {
  1906. X                        fprintf( stderr, 
  1907. X                            "ro:  unrecognized font name \"%c\" in input stream. \n", 
  1908. X                            d );
  1909. X                        }
  1910. X                }
  1911. X            break;
  1912. X        default:
  1913. X            putback( c );
  1914. X            break;
  1915. X        }
  1916. X    return TRUE;
  1917. X    }
  1918. X
  1919. X/****************************************/
  1920. X/* takes a .de and following lines and places
  1921. Xthe information in the table;    no macro
  1922. Xdefinition nesting permitted */
  1923. X
  1924. Xminsert()
  1925. X    {
  1926. X    register int n;
  1927. X    static char c, *src, *dst;
  1928. X    int keepon;
  1929. X    struct divfd *sptr;
  1930. X
  1931. X    if DEBUG
  1932. X        {
  1933. X        fprintf( stderr, "DEBUG:  enter minsert() \n" );
  1934. X        }
  1935. X
  1936. X    /* pass over command and following white space */
  1937. X
  1938. X    for ( src = ro_curline, c = *src; (c != ' ' ) && (c!='\n') && (c!='\t'); src++ )
  1939. X        {
  1940. X        c = *src;
  1941. X        }
  1942. X    for ( ; (c == ' ') || (c == '\t'); src++ ) 
  1943. X        {
  1944. X        c = *src;
  1945. X        }
  1946. X
  1947. X    /* Check to see if there is a name for the macro */
  1948. X
  1949. X    if ( ( c == '\n' ) || ( c == '\0' ))
  1950. X        {
  1951. X        if ( ro_verbose )
  1952. X            {
  1953. X            fprintf( stderr, "ERROR:  .de:  no name given. \n");
  1954. X            }
  1955. X        return -1;
  1956. X        }
  1957. X
  1958. X    /* Name detected, proceed to store the name */
  1959. X
  1960. X    else
  1961. X        {
  1962. X        if DEBUG
  1963. X            {
  1964. X            fprintf( stderr, "DEBUG:  macro name found; prepare to allocate memory. \n" );
  1965. X            }
  1966. X
  1967. X        if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
  1968. X            {
  1969. X            fprintf( stderr, "FATAL ERROR: cannot allocate memory for macro definition structure.  \n" );
  1970. X            exit ( -1 );
  1971. X            }
  1972. X
  1973. X        if DEBUG
  1974. X            {
  1975. X            fprintf( stderr, "DEBUG:  memory allocated for macro.\n" );
  1976. X            }
  1977. X
  1978. X        sptr->prev = mlink;             /* save previous link   */
  1979. X        mlink = sptr;            /* set mlink to this    */
  1980. X        n = 0;
  1981. X        while( class( c ) == BLACK )    /* Store each character */
  1982. X            {            /* of the macro name    */
  1983. X            sptr->nm[ n++ ] = c;
  1984. X            c = *( src++ );
  1985. X            }
  1986. X        sptr->nm[ n ] = '\0';
  1987. X
  1988. X        if DEBUG
  1989. X            {
  1990. X            fprintf( stderr, "DEBUG:  new macro name is <%s> \n",
  1991. X                sptr->nm );
  1992. X            }
  1993. X
  1994. X        }
  1995. X
  1996. X    /* Now read from instream until end of macro or EOF */
  1997. X
  1998. X    dst = tbuf;
  1999. X    keepon = 1;
  2000. X    while( keepon == 1 )
  2001. X        {
  2002. X        ro_gets( ro_curline );
  2003. X        src = ro_curline;
  2004. X
  2005. X        /* Check for end of macro */
  2006. X
  2007. X        if (( ro_curline[0] == COMMAND) && ( comtyp( ro_curline ) == EM ))
  2008. X            {
  2009. X            keepon = 0;
  2010. X            }
  2011. X        else            /* Not end; transfer to buffer    */
  2012. X            {
  2013. X            transfer( &src, &dst, (char) '\0' );
  2014. X            *(dst - 1) = '\n';    /* put a LF at the end     */
  2015. X            *dst = 0;        /* and a temp. delimiter */
  2016. X            }
  2017. X
  2018. X        if DEBUG
  2019. X            {
  2020. X            fprintf( stderr, "DEBUG:  minsert() current line <%s> \n", 
  2021. X                tbuf );
  2022. X            }
  2023. X
  2024. X        }
  2025. X    *( dst ) = '\0';                /* Terminate with \0            */
  2026. X
  2027. X    if DEBUG
  2028. X        {
  2029. X        fprintf( stderr, "DEBUG:  text of new macro is <%s> \n", tbuf );
  2030. X        }
  2031. X
  2032. X    /* allocate memory for this macro string and transfer the string to
  2033. X        the new location */ 
  2034. X
  2035. X    if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
  2036. X        {
  2037. X        fprintf( stderr, "Fatal error:  failed to allocate memory for macro string. \n" );
  2038. X        exit( -1 );
  2039. X        }
  2040. X    strcpy( sptr->mstr, tbuf );
  2041. X
  2042. X    }
  2043. X
  2044. X/****************************************/
  2045. X
  2046. Xshowm() /*lists macro definitions*/
  2047. X    {
  2048. X    struct divfd *pw;
  2049. X    char *pc;
  2050. X    fprintf( stderr, "MACROS DEFINED:\n");
  2051. X    pw = mlink;
  2052. X    while ( pw != NULL )
  2053. X        {
  2054. X        fprintf( stderr, "\t.%s\t<%s>\n", pw->nm, pw->mstr );
  2055. X        pw = pw->prev;
  2056. X        }
  2057. X    dashes();
  2058. X    }
  2059. X
  2060. X/****************************************/
  2061. X
  2062. Xchar *macq( line )              /*looks up name to see if it is a macro
  2063. X                definition.    If it is, returns the
  2064. X                corresponding string, else returns
  2065. X                FALSE.
  2066. X                */
  2067. X    char *line;
  2068. X    {
  2069. X    char c, *pc, wb[ LSZ ];
  2070. X    struct divfd *pstr;
  2071. X
  2072. X    pc = wb;
  2073. X    while ( class( c = *( ++line )) == BLACK )
  2074. X        {
  2075. X        *( pc++ ) = c;
  2076. X        }
  2077. X    *pc='\0';
  2078. X
  2079. X    pstr = find2( wb, mlink );
  2080. X    if ( pstr == NULL )
  2081. X        {
  2082. X        return NULL;
  2083. X        }
  2084. X    else
  2085. X        {
  2086. X        return ( pstr->mstr );
  2087. X        }
  2088. X    }
  2089. X
  2090. X/****************************************/
  2091. X
  2092. Xstruct divfd *
  2093. Xfind2( s, link)         /* finds or doesn't find s in table
  2094. X                of substitutions pointed to by link */
  2095. X    char *s;
  2096. X    struct divfd *link;
  2097. X    {
  2098. X    struct divfd *l;
  2099. X    char *pc;
  2100. X
  2101. X    l = link;
  2102. X    while ( l != NULL )
  2103. X        {
  2104. X        if ( !strcmp( s, l->nm ) )
  2105. X            {
  2106. X            return( l );    /* return structure pointer     */
  2107. X            }
  2108. X        l = l->prev;
  2109. X        }
  2110. X
  2111. X    return( NULL );                /* failed        */
  2112. X    }
  2113. X
  2114. X/****************************************/
  2115. X
  2116. ________This_Is_The_END________
  2117. if test `wc -l < ro_macr.c` -ne 620; then
  2118.     echo 'shar: ro_macr.c was damaged during transit (should have been 620 bytes)'
  2119. fi
  2120. fi        ; : end of overwriting check
  2121. exit 0
  2122.  
  2123.  
  2124.