home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / utility / 527 / qroff / qroff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-29  |  9.0 KB  |  384 lines

  1. /*
  2.  * qroff: a very quick and dirty text formatter, for stadel documentation.
  3.  */
  4. /*
  5.  * commands supported:
  6.  * $include <filename>        - include a file
  7.  * $section <level> <title>    - produce a section title
  8.  * $raw                - introduce raw code
  9.  * $cooked            - reenable the formatter
  10.  * $left <left-margin>        - set left margin
  11.  * $right <right-margin>    - set right margin
  12.  * $indent <paragraph-indent>    - set paragraph indent
  13.  * $skip <lines)        - skip some lines
  14.  * $par                - force paragraph break
  15.  */
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <stdarg.h>
  19.  
  20. #define    YES    1
  21. #define    NO    0
  22. #define    MAXWORD    160
  23.  
  24. int left_margin=4;            /* left page margin */
  25. int right_margin=70;            /* right page margin */
  26. int width=66;                /* page width (rm-lm) */
  27. int para_indent=4;            /* indent of first line of paragraph */
  28. char noformat=NO;            /* raw text output */
  29. int newpara=YES;            /* starting a new paragraph? */
  30.  
  31. char formatted[MAXWORD];        /* where text is processed to */
  32. int  fp=0;                /* index into the above */
  33. char inputted[MAXWORD];            /* latest line of text coming in */
  34. int  ip=0;                /* index into the above. */
  35.  
  36. #define    SECTIONS    10
  37. int  sections[SECTIONS];
  38.  
  39. #define    MAXFSTACK    20
  40.  
  41. struct filestack {
  42.     char name[80];
  43.     int  line;
  44. } stack[MAXFSTACK];
  45. int fsp = (-1);
  46.  
  47.  
  48. /*
  49.  * qroff main
  50.  */
  51. main(argc, argv)
  52. char **argv;
  53. {
  54.     register i;
  55.  
  56.     iformat();                /* initialize things */
  57.     fformat(NO, "style.qfm");
  58.     if (argc < 2)
  59.     sformat(stdin);
  60.     else for (i=1; i<argc; i++)
  61.     fformat(YES, argv[i]);
  62.     fsync();
  63.     exit(0);
  64. }
  65.  
  66.  
  67. /*
  68.  ************************************************
  69.  *    iformat() - initialize the formatter    *
  70.  ************************************************
  71.  */
  72. iformat()
  73. {
  74.     register i;
  75.  
  76.     for (i=0;i<SECTIONS; i++)
  77.     sections[i] = 0;
  78. }
  79.  
  80.  
  81. /*
  82.  ************************************************************************
  83.  *    fformat() - format a file.  If whine is true, complain about    *
  84.  *    files that can't be read.                    *
  85.  ************************************************************************
  86.  */
  87.  fformat(whine, file)
  88.  char *file;
  89.  {
  90.      FILE *fopen(), *thing;
  91.  
  92.     if (fsp >= MAXFSTACK-1)
  93.     message("stack overflow trying to read %s", file);
  94.     else if (thing=fopen(file, "r")) {
  95.     fsp++;
  96.     strcpy(stack[fsp].name, file);
  97.     stack[fsp].line = 0;
  98.     sformat(thing);
  99.     fclose(thing);
  100.     fsp--;
  101.     }
  102.     else if (whine)
  103.     message("cannot read %s", file);
  104. }
  105.  
  106.  
  107. /*
  108.  ****************************************************************
  109.  *    sformat() - take a stream and format it to stdout    *
  110.  ****************************************************************
  111.  */
  112. sformat(text)
  113. FILE *text;
  114. {
  115.     char thisword[MAXWORD];
  116.     char pc;
  117.     register idx, j, k;
  118.  
  119.     while (fgets(inputted, MAXWORD, text)) {
  120.     stack[fsp].line++;
  121.     if (!process())
  122.         if (noformat)
  123.         fputs(inputted, stdout);
  124.         else if (isblank()) {
  125.         fsync();
  126.         putchar('\n');
  127.         }
  128.         else {
  129.         for (idx=0; inputted[idx]; ) {
  130.             while (inputted[idx] && isspace(inputted[idx]))
  131.             idx++;
  132.             j = idx;
  133.             while (inputted[idx] && !isspace(inputted[idx]))
  134.             idx++;
  135.             if (newpara) {
  136.             newpara=NO;
  137.             for (k=0; k<para_indent; k++)
  138.                 thisword[k] = ' ';
  139.             }
  140.             else k = 0;
  141.             while (j<idx)
  142.             thisword[k++] = inputted[j++];
  143.             thisword[k] = 0;
  144.             if (fp > 0)
  145.             if (fp + strlen(thisword) >= width) {
  146.                 /*
  147.                  * if this word will make the screen wrap, kick out a
  148.                  * newline first.
  149.                  */
  150.                 outline();
  151.             }
  152.             else {
  153.                 pc = fp ? formatted[fp-1] : 254;
  154.                 if (pc != ' ')
  155.                 formatted[fp++] = ' ';
  156.                 if (strchr(".;:?!", pc))
  157.                 formatted[fp++] = ' ';
  158.             }
  159.             /*
  160.              * put the word and update curcol.  If the word was
  161.              * longer than WIDTH, we dump it straight and hope
  162.              * that the tty will wrap.
  163.              */
  164.             for (k=0; thisword[k]; )
  165.             formatted[fp++] = thisword[k++];
  166.         }
  167.         }
  168.     }
  169. }
  170.  
  171.  
  172.  
  173. /*
  174.  ************************************************
  175.  *    outline() - dump out a formatted line    *
  176.  ************************************************
  177.  */
  178. outline()
  179. {
  180.     register j;
  181.  
  182.     if (fp > 0) {
  183.     formatted[fp] = 0;
  184.     for (j=0; j<left_margin; j++)
  185.         putchar(' ');
  186.     printf("%s\n", formatted);
  187.     fp = 0;
  188.     }
  189. }
  190.  
  191.  
  192. /*
  193.  ************************************************************************
  194.  *    fsync() - if there is stuff waiting to be output, force it    *
  195.  *    out and reset the output buffer to start of line.        *
  196.  ************************************************************************
  197.  */
  198. fsync()
  199. {
  200.     outline();
  201.     newpara=YES;
  202. }
  203.  
  204.  
  205. /*
  206.  ************************************************************************
  207.  *    isblank() - is this line blank (for paragraphing things)    *
  208.  ************************************************************************
  209.  */
  210. isblank()
  211. {
  212.     register i;
  213.  
  214.     for (i=0; inputted[i] && isspace(inputted[i]); i++)
  215.     ;
  216.     return inputted[i] ? NO : YES;
  217. }
  218.  
  219.  
  220. /*
  221.  ************************************************
  222.  *    process() - a command in the text    *
  223.  ************************************************
  224.  */
  225. process()
  226. {
  227.     char cmd[MAXWORD], argument[MAXWORD];
  228.     int count;
  229.     int temp;
  230.     char plus = NO;
  231.     register i;
  232.     int shp;
  233.  
  234.     if (inputted[0] == '$') {
  235.     count = sscanf(inputted, "%s %s", cmd, argument);
  236.     if (stricmp(cmd, "$include") == 0) {
  237.         if (count == 2)
  238.         fformat(YES, argument);
  239.         else
  240.         message("$include syntax");
  241.     }
  242.     else if (stricmp(cmd, "$left") == 0) {
  243.         if (count != 2)
  244.         message("$left syntax");
  245.         else {
  246.         plus = (argument[0] == '+');
  247.         temp = atoi(plus ? (&argument[1]) : argument);
  248.         if (temp < 0 && left_margin + temp < 0)
  249.             message("left margin would be negative");
  250.         else if ((plus && left_margin + temp >= right_margin)
  251.                          || (temp > right_margin))
  252.             message("left margin would be greater than right margin");
  253.         else {
  254.             if (plus || temp < 0)
  255.             left_margin += temp;
  256.             else
  257.             left_margin = temp;
  258.             width = right_margin-left_margin;
  259.         }
  260.         }
  261.     }
  262.     else if (stricmp(cmd, "$right") == 0) {
  263.         if (count != 2)
  264.         message("$right syntax");
  265.         else {
  266.         plus = (argument[0] == '+');
  267.         temp = atoi(plus ? (&argument[1]) : argument);
  268.         if ((temp < 0 && right_margin + temp < left_margin)
  269.                 || (!plus && right_margin < left_margin))
  270.             message("right margin would be less than left margin");
  271.         else if ((plus && right_margin+temp > MAXWORD)
  272.                         || temp > MAXWORD)
  273.             message("right margin exceeds %d", MAXWORD);
  274.         else {
  275.             if (plus || temp < 0)
  276.             right_margin += temp;
  277.             else
  278.             right_margin = temp;
  279.             width = right_margin-left_margin;
  280.         }
  281.         }
  282.     }
  283.     else if (stricmp(cmd, "$indent") == 0) {
  284.         if (count != 2)
  285.         message("$indent syntax");
  286.         else {
  287.         temp = atoi(argument);
  288.         if (temp+left_margin > right_margin)
  289.             message("para indent exceeds right margin");
  290.         else if (temp+left_margin < 0)
  291.             message("para indent is less than zero");
  292.         else
  293.             para_indent = temp;
  294.         }
  295.     }
  296.     else if (stricmp(cmd, "$raw") == 0) {
  297.         fsync();
  298.         noformat = YES;
  299.     }
  300.     else if (stricmp(cmd, "$cooked") == 0)
  301.         noformat = NO;
  302.     else if (stricmp(cmd, "$section") == 0) {
  303.         for (i=0; inputted[i] && !isspace(inputted[i]); i++)
  304.         ;
  305.         while (inputted[i] && isspace(inputted[i]))
  306.         i++;
  307.         while (inputted[i] && !isspace(inputted[i]))
  308.         i++;
  309.         while (inputted[i] && isspace(inputted[i]))
  310.         i++;
  311.         if (count < 2 || !inputted[i])
  312.         message("$section syntax");
  313.         else {
  314.         temp = atoi(argument);
  315.         if (temp < 0 || temp > 9)
  316.             message("$section level must be 0 to 9");
  317.         else {
  318.             fsync();
  319.             shp = i;
  320.             sections[temp]++;
  321.             for (i=1+temp; i<10; i++)
  322.             sections[i] = 0;
  323.             for (i=0; i<=temp; i++)
  324.             printf("%s%d", (i==0)?"":".", sections[i]);
  325.             printf(") %s", &inputted[shp]);
  326.         }
  327.         }
  328.     }
  329.     else if (stricmp(cmd, "$center") == 0) {
  330.         for (i=0; inputted[i] && !isspace(inputted[i]); i++)
  331.         ;
  332.         while (inputted[i] && isspace(inputted[i]))
  333.         i++;
  334.         if (inputted[i]) {
  335.         fsync();
  336.         temp = (width-strlen(&inputted[i]))/2;
  337.         temp += left_margin;
  338.         while (temp-- > 0)
  339.             putchar(' ');
  340.         fputs(&inputted[i], stdout);
  341.         }
  342.         else
  343.         message("$center syntax");
  344.     }
  345.     else if (stricmp(cmd, "$par") == 0) {
  346.         fsync();
  347.     }
  348.     else if (stricmp(cmd, "$skip") == 0) {
  349.         if (count != 2)
  350.         message("$skip syntax");
  351.         else {
  352.         fsync();
  353.         temp = atoi(argument);
  354.         while (temp-- > 0)
  355.             putchar('\n');
  356.         }
  357.     }
  358.     else if (strcmp(cmd, "$") != 0)
  359.         message("%s not recognised", cmd);
  360.     return YES;
  361.     }
  362.     return NO;
  363. }
  364.  
  365.  
  366. /*
  367.  ************************************************
  368.  *    message() - print an error message    *
  369.  ************************************************
  370.  */
  371. message(format, args)
  372. char *format;
  373. {
  374.     va_list arg_ptr;
  375.  
  376.     va_start(arg_ptr, format);
  377.  
  378.     fprintf(stderr, "qroff: ");
  379.     if (fsp >= 0)
  380.     fprintf(stderr, "(%s) line %d: ", stack[fsp].name, stack[fsp].line);
  381.     vfprintf(stderr, format, arg_ptr);
  382.     putc('\n', stderr);
  383. }
  384.