home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 213_01 / cbprepr.c < prev    next >
Text File  |  1979-12-31  |  19KB  |  920 lines

  1. /* CBPREPR.C    VERS:- 01.00  DATE:- 09/26/86  TIME:- 09:36:05 PM */
  2. /*
  3. %CC1 $1.C -O -X -E6000
  4. %CLINK $1 DIO -S -E6000
  5. %DELETE $1.CRL 
  6. */
  7. /* 
  8. Description:
  9.  
  10. Filter to prepare C code for formatting:
  11.     add and delete white space to produce consistent text;
  12.     introduce newlines to produce one statment per line;
  13.     left justify all lines.
  14.  
  15. DIO redirection.
  16.  
  17. To indent according to control level, output from CBPREP
  18. must be filtered by CB, the formatting program written 
  19. by W.C. Colley and R. Hollinbeck and based on a unix utility.
  20.  
  21. CBPREP uses the routines getch() and comment() of CB.
  22.  
  23.  
  24. By J.A. Rupley, Tucson, Arizona
  25. Coded for BDS C compiler, version 1.50a
  26. */
  27.  
  28. #include "bdscio.h"
  29. #include "dio.h"
  30.  
  31. /*debug*/
  32. /*
  33. #define DEBUG
  34. */
  35.  
  36. int j;
  37. int cc;
  38. int peek;
  39. int sflag;
  40. int expr_flag;
  41. int lastchar;
  42. int c;
  43. int control_keys, else_key, do_key, case_key, default_key, flow_keys;
  44. int typedef_key, struct_key, union_key, c_keys, keys_total;
  45. int close_loc, paren_count, ctrl_count, last_count, last_key;
  46.  
  47. char string[200];
  48. char *keyword[30];
  49.  
  50. main(argc, argv)
  51. int argc;
  52. char *argv[];
  53. {
  54.     int k;
  55.     int count;
  56.  
  57.     dioinit(&argc, argv);
  58.  
  59.     /*exit if improper command line parameters*/
  60.     if (!_dioinflg)
  61.         use_mess();
  62.  
  63.     /*set up pointers to keyword strings*/
  64.     init_key();
  65.  
  66.     close_loc = paren_count = ctrl_count = last_count = 0;
  67.     last_key = keys_total + 1;
  68.     expr_flag = 0;
  69.     sflag = 0;
  70.     peek = -1;
  71.     j = 0;
  72.  
  73.     /*  Start of text manipulation.  */
  74.  
  75.     while (((c = getchr()) != EOF) && (c != CPMEOF))
  76.     {
  77.         /*at terminators reset control values*/
  78.         if (c == '}' || c == '{' || c == ':')
  79.             paren_count = ctrl_count = 0;
  80.  
  81.         switch (c)
  82.         {
  83.             /*no white space starting line*/
  84.             /*only single spaces elsewhere*/
  85.         case '\t' :
  86.             c = ' ';
  87.         case ' ' :
  88.             while (((peek = getchr()) == ' ') || (peek == '\t'))
  89.                 peek = -1;
  90.             if (j)
  91.                 string[j++] = c;
  92.             break;
  93.             /*at end of line, perform additional*/
  94.             /*formatting checks on entire line*/
  95.         case '\n' :
  96.             if (check_puts())
  97.                 printf("\n");
  98.             break;
  99.             /*block delimiters on separate line*/
  100.         case '}' :
  101.         case '{' :
  102.             if (j)
  103.                 if (check_puts())
  104.                     printf("\n");
  105.             string[j++] = c;
  106.             while (((peek = getchr()) == ' ') || (peek == '\t'))
  107.                 peek = -1;
  108.             if (peek != '\n')
  109.             {
  110.                 check_puts();
  111.                 printf("\n");
  112.             }
  113.             break;
  114.             /*space after, no space before ; and ,*/
  115.         case ';' :
  116.         case ',' :
  117.             if (j && (string[j - 1] == ' '))
  118.                 j--;
  119.             string[j++] = c;
  120.             if (((peek = getchr()) != ' ') && (peek != '\t'))
  121.                 string[j++] = ' ';
  122.             break;
  123.             /*remove some spaces adjacent to brackets/parentheses*/
  124.             /* -[- -]  -(- -) */
  125.             /*add space if identifier follows close parenthesis*/
  126.             /* )+ident  ]+ident*/
  127.         case '(' :
  128.         case '[' :
  129.             while (((peek = getchr()) == ' ') || (peek == '\t'))
  130.                 peek = -1;
  131.             if ((j > 1) && (string[j - 1] == ' ') &&
  132.                 isname_char(string[j - 2]))
  133.                 j--;
  134.             string[j++] = c;
  135.             break;
  136.         case ')' :
  137.         case ']' :
  138.             if (j && (string[j - 1] == ' '))
  139.                 j--;
  140.             string[j++] = c;
  141.             if (isname_char(peek = getchr()))
  142.                 string[j++] = ' ';
  143.             break;
  144.             /*pass over text*/
  145.             /*delete imbedded newlines*/
  146.         case '"' :
  147.         case '\'' :
  148.             string[j++] = c;
  149.             while ((cc = getchr()) != c)
  150.             {
  151.                 string[j++] = cc;
  152.                 if (cc == '\n')
  153.                     j--;
  154.                 if (cc == '\\')
  155.                     string[j++] = getchr();
  156.             }
  157.             string[j++] = cc;
  158.             break;
  159.         case '\\' :
  160.             string[j++] = c;
  161.             string[j++] = getchr();
  162.             break;
  163.             /*pass over #defines*/
  164.         case '#' :
  165.             if (j)
  166.                 if (check_puts())
  167.                     printf("\n");
  168.             string[j++] = c;
  169.             while ((cc = getchr()) != '\n')
  170.                 string[j++] = cc;
  171.             string[j++] = cc;
  172.             puts();
  173.             break;
  174.             /*pass over comments*/
  175.             /*add lead tab if comment follows text*/
  176.             /*if "/" not comment start, fall through to default*/
  177.             /*there is also comment check during operator output*/
  178.         case '/' :
  179.             if ((peek = getchr()) == '*')
  180.             {
  181.                 comment();
  182.                 break;
  183.             }
  184.         default :
  185.             if (isoperator(c))
  186.                 operators();
  187.             else
  188.                 string[j++] = c;
  189.             break;
  190.         }
  191.     }
  192.     dioflush();
  193.     exit();
  194. }
  195.  
  196.         /*page eject*/
  197. /*
  198. main routine to introduce and delete spaces from text with operators
  199. */
  200.  
  201. void operators()
  202. {
  203.     /*checks on special expression operators or operator pairs*/
  204.     /*remove lead and trail spaces as appropriate*/
  205.     peek = getchr();
  206.     if ((c == peek) && ((c == '+') || (c == '-')))
  207.     {
  208.         string[j++] = c;
  209.         string[j++] = peek;
  210.         peek = -1;
  211.         return;
  212.     }
  213.     while (string[j - 1] == ' ')
  214.         j--;
  215.     if ((c == '-') && (peek == '>'))
  216.     {
  217.         string[j++] = c;
  218.         string[j++] = peek;
  219.         peek = -1;
  220.         while (((c = getchr()) == ' ') || (c == '\t'))
  221.             ;
  222.         peek = c;
  223.         return;
  224.     }
  225.     if (c == '.')
  226.     {
  227.         string[j++] = c;
  228.         while (((c = getchr()) == ' ') || (c == '\t'))
  229.             ;
  230.         peek = c;
  231.         return;
  232.     }
  233.     while (((cc = getchr()) == ' ') || (cc == '\t'))
  234.         ;
  235.     peek = cc;
  236.  
  237.     /*test whether last character sequence is expression*/
  238.     /*for start of line (j=0), check_puts() tested end of prev line*/
  239.     if (j)
  240.         expr_flag = isexpression(string[j - 1]);
  241.     /*add lead space (trail space is as appropriate added below)*/
  242.     if (j && (string[j - 1] != '(') && (string[j - 1] != '['))
  243.         string[j++] = ' ';
  244.  
  245.     /*expr_flag TRUE is followed by a binary or assign operator*/
  246.     if (expr_flag)
  247.     {
  248.         while (isbinop(c))
  249.         {
  250.             peek = getchr();
  251.             if ((c == '/') && (peek == '*'))
  252.             {
  253.                 comment();        /*watch for comments*/
  254.                 return;
  255.             }
  256.             string[j++] = c;
  257.             while (((c = getchr()) == ' ') || (c == '\t'))
  258.                 ;
  259.             expr_flag = 0;
  260.         }
  261.         string[j++] = ' ';
  262.     }
  263.  
  264.     /*handling of unary operator sequences*/
  265.     /*for when expr_flag = 0 at entry to operators()*/
  266.     /*or on fall through from above block executed when expr_flag = 1*/
  267.     while (isoperator(c))
  268.     {
  269.         string[j++] = c;
  270.         while (((c = getchr()) == ' ') || (c == '\t'))
  271.             ;
  272.     }
  273.     peek = c;
  274.     return;
  275. }
  276.  
  277.         /*page eject*/
  278. /*
  279. return true if last character sequence is an expression;
  280. enter routine with string index j set at last character location + 1
  281. ie at the end of the string;
  282. */
  283.  
  284. /*last_count = string position of last keyword found*/
  285. /*last_key = identifier of last keyword*/
  286. /*paren_count = count of control exprsn parenthesis imbalance*/
  287. /*ctrl_count = string position after last parenthesis check*/
  288. /*close_loc = string position of close of parenthesis*/
  289. /*above externals reset as needed below or in check_puts()*/
  290.  
  291. int isexpression(testchar)
  292. char testchar;
  293. {
  294.     int k, l, count;
  295.     int pcount;
  296.     int temp;
  297.     char word[80];
  298.  
  299.     k = last_count;
  300.     last_key = keys_total + 1;
  301.     string[j] = '\0';
  302.  
  303.     /*can an open exprsn be closed*/
  304.     /*if so, set close_loc flag and exit if terminal ')'*/
  305.     if (paren_count)
  306.     {
  307.         count = end_paren(&string[ctrl_count], &paren_count);
  308.         if (!paren_count)
  309.         {
  310.             close_loc = ctrl_count += count;
  311.             if (!string[close_loc])
  312.                 return FALSE;
  313.         }
  314.         else
  315.             ctrl_count = strlen(string);
  316.     }
  317.  
  318.     /*check if previous word == expression*/
  319.     switch (testchar)
  320.     {
  321.     case '\'' :
  322.     case '"' :
  323.     case '_' :
  324.     case '+' :
  325.     case '-' :
  326.     case ']' :
  327.     case '.' :        /*for float constants*/
  328.         return TRUE;
  329.     default :
  330.         if (isdigit(testchar))
  331.             return TRUE;
  332.         if (!isalpha(testchar) && (testchar != ')'))
  333.             return FALSE;
  334.  
  335.         /*keywords are not expressions*/
  336.         /*and may change syntax for following operator*/
  337.  
  338.         /*locate last keyword in line*/
  339.         /*if a control keyword is met*/
  340.         /*check parenthesis balance for following expression*/
  341.         while (k < j)
  342.         {
  343.             count = next_alpha_word(&string[k], word);
  344.             k += count;
  345.             if (strlen(word) < 2 || strlen(word) > 8)
  346.                 continue;
  347.             for (l = 0; l <= keys_total; l++)
  348.                 if (!strcmp(word, keyword[l]))
  349.                 {
  350.                     last_count = k;
  351.                     last_key = l;
  352.                     if (l <= control_keys)
  353.                     {
  354.                         paren_count = 0;
  355.                         ctrl_count = last_count;
  356.                         count = end_paren(&string[ctrl_count], &paren_count);
  357.                         if (!paren_count)
  358.                             ctrl_count += count;
  359.                         else
  360.                             ctrl_count = strlen(string);
  361.                     }
  362.                     break;
  363.                 }
  364.         }
  365.  
  366.         /*set last_count and*/
  367.         /*return if no keyword*/
  368.         if (last_key > keys_total)
  369.         {
  370.             last_count = strlen(string);
  371.             return TRUE;
  372.         }
  373.         else
  374.             while (string[last_count] == ' ')
  375.             last_count++;
  376.  
  377.         /*return if keyword or (keyword) at end of line*/
  378.         if (!string[last_count] || string[last_count] == ')')
  379.             return FALSE;
  380.  
  381.         /*assume the following declarations are the last on a line*/
  382.         if (last_key == union_key || last_key == struct_key ||
  383.             last_key == typedef_key)
  384.             return FALSE;
  385.  
  386.         if (last_key > control_keys)
  387.             return TRUE;        /*not control keyword*/
  388.  
  389.         /*check exprsn following control keyword*/
  390.         if (!paren_count)
  391.         {
  392.             if (!string[ctrl_count])
  393.                 return FALSE;        /*control exprsn ends line*/
  394.             else
  395.                 return TRUE;
  396.         }
  397.         else
  398.             return TRUE;        /*unclosed control expression*/
  399.     }
  400. }
  401.  
  402.         /*page eject*/
  403. /*
  404. process line buffer, including a call to line_check(),
  405. then print it
  406. */
  407.  
  408. int check_puts()
  409. {
  410.     /*terminate string*/
  411.     if (!j)
  412.         return 1;
  413.     else
  414.         string[j] = '\0';
  415.  
  416.     /*remove trailing spaces*/
  417.     while (string[j - 1] == ' ')
  418.         string[j--] = '\0';
  419.  
  420.     /*set expression flag for next line and try to close open expressions*/
  421.     expr_flag = isexpression(string[j - 1]);
  422.  
  423.     /*insert newline if open expression was closed*/
  424.     if (close_loc && close_loc < (j - 1))
  425.     {
  426.         while (string[close_loc] == ' ')
  427.             close_loc++;
  428.         insert_char(string, close_loc, '\n');
  429.     }
  430.  
  431.     /*reset control values*/
  432.     last_count = 0;
  433.     last_key = keys_total + 1;
  434.     ctrl_count = 0;
  435.     close_loc = 0;
  436.  
  437.     /*process string*/
  438.     if (!line_check(string))
  439.         return 0;
  440.     else
  441.         j = strlen(string);
  442.  
  443.     /*remove trailing spaces again*/
  444.     while (string[j - 1] == ' ')
  445.         string[j--] = '\0';
  446.  
  447.     /*print buffer and continue*/
  448.     puts();
  449.     return 1;
  450. }
  451.  
  452.         /*page eject*/
  453. /*
  454. main routine for processing line of text
  455. to make changes not done on the character scan
  456. */
  457.  
  458. int line_check(teststr)
  459. char *teststr;
  460. {
  461.     int k, l;
  462.     int count;
  463.     int tempchar;
  464.     int pcount;
  465.  
  466.     /*space after if, while, for, switch, etc, */
  467.     for (k = 0; k <= keys_total; k++)
  468.     {
  469.         if (count = str1_start_str2(keyword[k], teststr))
  470.         {
  471.             tempchar = teststr[count];
  472.             /*reject if keyword is first part of longer name*/
  473.             /*reject if space present or end of exprsn or line*/
  474.             if ((tempchar != ' ') && (tempchar != ';') &&
  475.                 (tempchar != ')') && (tempchar != '\n') &&
  476.                 !isname_char(tempchar))
  477.                 count = insert_char(teststr, count, ' ');
  478.             break;
  479.         }
  480.         count = 0;
  481.     }
  482.  
  483.     /*newline after (control expression)*/
  484.     /*if newline needed, then process remainder of line*/
  485.     /*so have only one statement or control expression per line*/
  486.     if (count && (k <= control_keys))
  487.     {
  488.         /*go to end of control expression */
  489.         pcount = 0;
  490.         if ((count = end_paren(teststr, &pcount)) > 0)
  491.             return break_line(teststr, count);
  492.         count = 0;
  493.     }
  494.  
  495.     /*newline after else and do */
  496.     if (count && ((k == do_key) || (k == else_key)))
  497.     {
  498.         /*reject if keyword is first part of longer name*/
  499.         if (!isname_char(teststr[count]))
  500.             return break_line(teststr, count);
  501.         count = 0;
  502.     }
  503.  
  504.     /*newline after : except if operator (-?-:-) */
  505.     /*allow (case '-' :) and (anyword :) */
  506.     if (count && ((k == case_key) || (k == default_key)))
  507.     {
  508.         if (count = str1_in_str2(":", teststr))
  509.             return break_line(teststr, count);
  510.         count = 0;
  511.     }
  512.     /*this sequence destroys the value of count = keyword ident*/
  513.     if (count = str1_in_str2(" ", teststr))
  514.     {
  515.         count = good_char(teststr, count);
  516.         if (teststr[count++] == ':')
  517.             return break_line(teststr, count);
  518.     }
  519.  
  520.     /*only one statement per line*/
  521.     count = 0;
  522.     while (teststr[count] != '\0')
  523.     {
  524.         count = good_char(teststr, count);
  525.         if (((tempchar = teststr[count++]) == ';') ||
  526.             (tempchar == '}') || (tempchar == '{'))
  527.             return break_line(teststr, count);
  528.     }
  529.     return 1;
  530. }
  531.  
  532.         /*page eject*/
  533. void use_mess()
  534. {
  535.     printf(
  536.     "\nUSAGE:\n");
  537.     printf(
  538.     "     cbprep  <input_fid  [>out_fid or |DIO_pipe or default = crt]\n\n");
  539.     printf(
  540.     "one of three formatting filters:\n\n");
  541.     printf(
  542.     "unvanuys - converts keywords of Van Nuys Toolkit to standard K & R 'c'\n");
  543.     printf(
  544.     "cbprep - produces consistent spacing of 'c' text and one statement per line\n");
  545.     printf(
  546.     "         output must be filtered by cb\n");
  547.     printf(
  548.     "cb - indents according to control level\n\n");
  549.  
  550.     dioexit();
  551. }
  552.  
  553. /*
  554. "c" reserved words---
  555. the first four require a control expression following;
  556. some of the others may have an exprsn or statemnt etc following;
  557. */
  558.  
  559. void init_key()
  560. {
  561.     int k;
  562.  
  563.     k = 0;
  564.     keyword[k++] = "if";
  565.     keyword[k++] = "while";
  566.     keyword[k++] = "for";
  567.     keyword[k++] = "switch";
  568.     control_keys = k - 1;        /*end of keywrds requiring exprsn*/
  569.     keyword[k++] = "do";
  570.     do_key = k - 1;
  571.     keyword[k++] = "else";
  572.     else_key = k - 1;        /*end of keywrds with following line feed */
  573.     keyword[k++] = "return";
  574.     keyword[k++] = "case";
  575.     case_key = k - 1;
  576.     keyword[k++] = "default";
  577.     default_key = k - 1;
  578.     keyword[k++] = "break";
  579.     keyword[k++] = "continue";
  580.     keyword[k++] = "goto";
  581.     flow_keys = k - 1;        /*end of keywords for flow control*/
  582.     keyword[k++] = "auto";
  583.     keyword[k++] = "static";
  584.     keyword[k++] = "extern";
  585.     keyword[k++] = "register";
  586.     keyword[k++] = "typedef";
  587.     typedef_key = k - 1;        /*typedef keyword*/
  588.     keyword[k++] = "char";
  589.     keyword[k++] = "short";
  590.     keyword[k++] = "int";
  591.     keyword[k++] = "long";
  592.     keyword[k++] = "unsigned";
  593.     keyword[k++] = "float";
  594.     keyword[k++] = "double";
  595.     keyword[k++] = "struct";
  596.     struct_key = k - 1;        /*struct keyword*/
  597.     keyword[k++] = "union";
  598.     union_key = k - 1;        /*union keyword*/
  599.     keyword[k++] = "sizeof";
  600.     c_keys = k - 1;        /*end of 'c' keywords*/
  601.     keyword[k++] = "FILE";        /*additional keywords*/
  602.     keys_total = k - 1;
  603. }
  604.  
  605. int getchr()
  606. {
  607.     int tempchar;
  608.  
  609.     tempchar = lastchar;
  610.     lastchar = (peek < 0) ? getchar() : peek;
  611.     if ((lastchar == EOF) || (lastchar == CPMEOF))
  612.     {
  613.         if (tempchar != '\n')
  614.         {
  615.             puts();
  616.             printf("\n");
  617.         }
  618.         dioflush();
  619.         exit();
  620.     }
  621.     else
  622.         lastchar = (lastchar & 0x7f);
  623.     peek = -1;
  624.     return (lastchar == '\r' ? getchr() : lastchar);
  625. }
  626.  
  627. void puts()
  628. {
  629.     if (!j)
  630.         return;
  631.     string[j] = '\0';
  632.     printf("%s", string);
  633.     j = 0;
  634.     return;
  635. }
  636.  
  637. void comment()
  638. {
  639.  
  640.     if (j)
  641.     {
  642.         check_puts();
  643.         printf("        ");
  644.     }
  645.     string[j++] = c;
  646.     string[j++] = peek;
  647.     peek = -1;
  648.     sflag = 1;
  649. rep :
  650.     while ((c = string[j++] = getchr()) != '*')
  651.         if (c == '\n')
  652.             puts();
  653.     if ((j > 1) && (string[j - 2] == '/'))
  654.     {
  655.         sflag++;
  656.         goto rep;
  657.     }
  658.     while ((c = string[j++] = getchr()) == '*')
  659.         ;
  660.     if ((c == '/') && !(--sflag))
  661.     {
  662.         puts();
  663.         return;
  664.     }
  665.     else
  666.         if (c == '\n')
  667.         puts();
  668.     goto rep;
  669. }
  670.  
  671. int isoperator(testchar)
  672. int testchar;
  673. {
  674.     switch (testchar)
  675.     {
  676.     case '!' :
  677.     case '%' :
  678.     case '&' :
  679.     case '*' :
  680.     case '+' :
  681.     case '-' :
  682.     case '/' :
  683.     case ':' :
  684.     case '<' :
  685.     case '=' :
  686.     case '>' :
  687.     case '?' :
  688.     case '^' :
  689.     case '|' :
  690.     case '~' :
  691.     case '.' :
  692.         return TRUE;
  693.     default :
  694.         return FALSE;
  695.     }
  696. }
  697.  
  698. int isbinop(testchar)
  699. char testchar;
  700. {
  701.     switch (testchar)
  702.     {
  703.     case '%' :
  704.     case '/' :
  705.     case ':' :
  706.     case '<' :
  707.     case '=' :
  708.     case '>' :
  709.     case '?' :
  710.     case '^' :
  711.     case '|' :
  712.         return TRUE;
  713.     case '&' :
  714.         if ((peek == '&') || (string[j - 1] == '&'))
  715.             return TRUE;
  716.     case '*' :
  717.     case '-' :
  718.     case '+' :
  719.         if (expr_flag)
  720.             return TRUE;
  721.     case '!' :
  722.         if (peek == '=')
  723.             return TRUE;
  724.     default :
  725.         return FALSE;
  726.     }
  727. }
  728.  
  729. int isname_char(testchar)
  730. char testchar;
  731. {
  732.     if (isalpha(testchar) || isdigit(testchar) || (testchar == '_'))
  733.         return TRUE;
  734.     else
  735.         return FALSE;
  736. }
  737.  
  738. /*
  739. find next all alpha word contained in string;
  740. skip over text within " or ';
  741. copy word to buffer;
  742. return position in string of character following end of word;
  743. */
  744.  
  745. int next_alpha_word(str, buf)
  746. char *str, *buf;
  747. {
  748.     int count, word;
  749.  
  750.     count = 0;
  751. restart :
  752.     word = 0;
  753.  
  754.     /*find next alpha character or end of string*/
  755.     while (!isalpha(str[count = good_char(str, count)]) && str[count])
  756.         count++;
  757.  
  758.     /*copy characters into buffer until meet non-alpha character*/
  759.     /*if non-alpha is part of a 'c' identifier*/
  760.     /*go to end of identifier and then continue search*/
  761.     while (isname_char(str[count]))
  762.     {
  763.         if (!isalpha(str[count]))
  764.         {
  765.             while (isname_char(str[count]))
  766.                 count++;
  767.             goto restart;
  768.         }
  769.         else
  770.             buf[word++] = str[count++];
  771.     }
  772.  
  773.     /*exit if end of string*/
  774.     buf[word] = '\0';
  775.     return count;
  776. }
  777.  
  778. /*
  779. the next two functions perform as follows:
  780. if string 1 is found in string2, return the position of the character 
  781. in str2 immediately following the str1 sequence;
  782. else 0 is returned
  783. */
  784.  
  785. int str1_in_str2(str1, str2)
  786. char *str1, *str2;
  787. {
  788.     int i, loc;
  789.  
  790.     for (i = 0; i < strlen(str2); i++)
  791.         if (loc = str1_start_str2(str1, &str2[i]))
  792.             return (loc + i);
  793.     return 0;
  794. }
  795.  
  796. int str1_start_str2(str1, str2)
  797. char *str1, *str2;
  798. {
  799.     int loc;
  800.  
  801.     loc = 0;
  802.     while (*str1++ == *str2++)
  803.     {
  804.         loc++;
  805.         if (!*str1)
  806.             return loc;
  807.         if (!*str2)
  808.             return 0;
  809.     }
  810.     return 0;
  811. }
  812.  
  813. /*
  814. test if string pointer is at good character
  815. = non_text and non_space character;
  816. if it is not, then advance pointer to next good character
  817. */
  818.  
  819. int good_char(str, loc)
  820. char *str;
  821. int loc;
  822. {
  823.     int passchar, tempchar;
  824.  
  825.     while (1)
  826.     {
  827.         if (!(tempchar = str[loc++]))
  828.             return --loc;
  829.  
  830.         if ((tempchar == '"') || (tempchar == '\''))
  831.         {
  832.             while ((passchar = str[loc++]) != tempchar)
  833.             {
  834.                 if (passchar == '\\')
  835.                     passchar = str[loc++];
  836.             }
  837.             continue;
  838.         }
  839.         if (tempchar == '\\')
  840.             tempchar = str[loc++];
  841.  
  842.         if (tempchar != ' ')
  843.             return --loc;
  844.     }
  845. }
  846.  
  847. int break_line(teststr, count)
  848. char *teststr;
  849. int count;
  850. {
  851.     count = good_char(teststr, count);
  852.     if (teststr[count] != '\0')
  853.     {
  854.         if (teststr[count] != '\n')
  855.             count = insert_char(teststr, count, '\n');
  856.         /*recursive call to check out rest of line*/
  857.         return line_check(&teststr[count]);
  858.     }
  859.     else
  860.         return 1;
  861. }
  862.  
  863. int insert_char(str, loc, newchar)
  864. char *str;
  865. int loc, newchar;
  866. {
  867.     char tempstr[200];
  868.     int k;
  869.  
  870.     strcpy(tempstr, str);
  871.     k = loc;
  872.     if (newchar == '\n')
  873.         while (tempstr[loc - 1] == ' ')
  874.             loc--;
  875.     tempstr[loc] = newchar;
  876.     strcpy(&tempstr[loc + 1], &str[k]);
  877.     strcpy(str, tempstr);
  878.     return ++loc;
  879. }
  880.  
  881. /*
  882. check for balance of parentheses within string:
  883. return 0 if no parentheses present and enter with *p_pflag = 0;
  884. return -1 if imbalance;
  885. else return pointer to next character after close of parentheses;
  886. enter with pointer p_pflag to location with current value of paren count,
  887. which is revised according to the search;
  888. */
  889.  
  890. int end_paren(str, p_pflag)
  891. char *str;
  892. int *p_pflag;
  893. {
  894.     int loc, pflag;
  895.  
  896.     pflag = *p_pflag;
  897.     loc = 0;
  898.     if (pflag == 0)
  899.         if (loc = str1_in_str2("(", str))
  900.             pflag++;
  901.     while (pflag)
  902.     {
  903.         loc = good_char(str, loc);
  904.         if (str[loc] == '(')
  905.             pflag++;
  906.         if (str[loc] == ')')
  907.             pflag--;
  908.         if (str[loc] == '\0')
  909.         {
  910.             loc = -1;
  911.             break;
  912.         }
  913.         loc++;
  914.     }
  915.     *p_pflag = pflag;
  916.     return loc;
  917. }
  918.  
  919.  
  920.