home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 195_01 / change.c < prev    next >
Text File  |  1987-10-05  |  7KB  |  310 lines

  1. /* [CHANGE.C of JUGPDS Vol.18]
  2. *****************************************************************
  3. *                                *
  4. *    Written by  Hakuo Katayose (JUG-CP/M No.179)        *
  5. *            49-114 Kawauchi-Sanjuunin-machi        *
  6. *            Sendai, Miyagi 980                          *
  7. *            Phone: 0222-61-3219                *
  8. *                                *
  9. *    Edited & tested by Y. Monma (JUG-C/M Disk Editor)       * 
  10. *                                *
  11. *****************************************************************
  12. */
  13.  
  14. /* change - change "from" into "to" 
  15.  
  16.     Usage: change [-l][-v] from [to] <infile [>outfile]
  17.  
  18. where
  19.     -l: line # 
  20.     -v: 
  21.  
  22. */
  23.  
  24. #include "stdio.h"
  25. #include "def.h"
  26. #include <dio.h>
  27.  
  28. main(argc, argv)
  29. int    argc;
  30. char    **argv;
  31.  
  32. {
  33.     char    lin[MAXLINE], pat[MAXPAT], new[MAXLINE], sub[10][MAXLINE];
  34.     char    cmd[2][MAXLINE];
  35.     char    opt_l, opt_v, *ap;
  36.     int    i, k, lastm, m, lno, maxsub, nl, nx;
  37.  
  38.     dioinit(&argc, argv);
  39.     opt_l = opt_v = OFF;
  40.     nl = 1; i = 0;
  41.     while (--argc > 0) {
  42.         if ((*++argv)[0] == '-') /* check option */
  43.             for (ap = argv[0]+1; *ap != '\0'; ap++) {
  44.                 if (tolower(*ap) == 'l') {
  45.                     opt_l = ON;
  46.                     nl = 0;
  47.                     for (; isdigit(nx = *(ap+1)); ap++)
  48.                         nl = nl*10 + nx - '0';
  49.                     nl = (nl == 0 ? 1 : nl);
  50.                     }
  51.                 else if (tolower(*ap) == 'v')
  52.                     opt_v = ON;
  53.                 else
  54.                     fprintf(STDERR,
  55.                     "[-%c]:Illigal option\n",tolower(*ap));
  56.                 }
  57.         else if (i < 2)
  58.             strcpy(cmd[i++], *argv);
  59.         else
  60.             remark("Too many arguments!\n");
  61.         }
  62.     if (i == 0)
  63.         error("Usage: change [-l][-v] from [to] <infile [>outfile]\n");
  64.     if ((maxsub = getpat(cmd[0], pat)) == ERROR)
  65.         error("Illegal from pattern.\n");
  66.     if (i > 1) {
  67.         if (getsub(cmd[1], sub[0]) == ERROR)
  68.             error("Illegal to pattern.\n");
  69.         }
  70.     else
  71.         sub[0][0] = EOS;
  72.     printf("Changed to "); puts(&sub[0][0]); printf("\n");
  73.     lno = 0;
  74.     while (getlin(lin, MAXLINE) > 0) {
  75.         lno += nl;    k = 0;    lastm =    -1;
  76.         for (i = 0; lin[i] != EOS; ) {
  77.             m = amatch(lin, i, pat, sub, maxsub);
  78.             if (m >= 0 && lastm != m) { /* replace matched text */
  79.                 catsub(lin, i, m, new, &k, MAXLINE, sub);
  80.                 lastm = m;
  81.                 }
  82.             if (m == ERROR || m == i) /* no match or null match */
  83.                 addset(lin[i++], new, &k, MAXLINE);
  84.             else            /* skip matched text */
  85.                 i = m;
  86.             }
  87.         if (k >= MAXLINE) {
  88.             new[MAXLINE] = EOS;
  89.             fprintf(STDERR, "line truncated.\n:%s", new);
  90.             printf("        %s\n", new);
  91.             }
  92.         else
  93.             new[k] = EOS;
  94.         if (lastm >= 0)
  95.             if (opt_l == ON)
  96.                 fprintf(STDERR, "%6d: %s", lno, new);
  97.             else
  98.                 fprintf(STDERR, "%s", new);
  99.         if (opt_v == ON)
  100.             if (opt_l == ON)
  101.                 printf("%6d: %s", lno, new);
  102.             else
  103.                 printf("%s", new );
  104.         }
  105.     dioflush();
  106. }
  107.  
  108.  
  109. /* catsub - add replacement text to end of new */
  110. catsub(lin, from, to, new, k, maxnew, sub)
  111. int    from, to, *k, maxnew;
  112. char    lin[], new[], sub[10][MAXPAT];
  113.  
  114. {
  115.     int    i, j, ns;
  116.  
  117.     for (i = 0; sub[0][i] != EOS && *k < maxnew; i++) {
  118.         if (sub[0][i] == DITTO) {
  119.             for (j = from; j < to && *k < maxnew; j++)
  120.                 new[(*k)++] = lin[j];
  121.             }
  122.         else if (sub[0][i] == SUBSTRG) {
  123.             ns = sub[0][++i] - '0';
  124.             for (j = 0; sub[ns][j] != EOS && *k < maxnew; j++)
  125.                 new[(*k)++] = sub[ns][j];
  126.             }
  127.         else if (*k >= maxnew)
  128.             break;
  129.         else
  130.             new[(*k)++] = sub[0][i];
  131.         }
  132. }
  133.  
  134. /* getsub - get substitution pattern into sub */
  135. getsub(arg, sub)
  136. char    *arg, *sub;
  137.  
  138. {
  139.     return(maksub(arg, 0, EOS, sub));
  140. }
  141.  
  142. /* maksub -make substitution string in sub */
  143. maksub(arg, from, delim, sub)
  144. char    delim, arg[], *sub;
  145. int    from;
  146.  
  147. {
  148.     int    i, j;
  149.  
  150.     for (i = from; arg[i] != delim && arg[i] != EOS; i++)
  151.         if (arg[i] == AND)
  152.             *sub++ = DITTO;
  153.         else if (arg[i] == ESCAPE && (isdigit(arg[i+1]))) {
  154.             *sub++ = SUBSTRG;
  155.             *sub++ = arg[++i];
  156.             }
  157.         else
  158.             *sub++ = esc(arg, &i);
  159.     *sub = EOS;
  160.     if (arg[i] != delim)
  161.         return ERROR;
  162.     if (strlen(sub) > MAXLINE)
  163.         return ERROR;
  164.     return(i);
  165. }
  166.  
  167.  
  168. /* getpat - convert argument into pattern */
  169. getpat(arg, pat)
  170. char    *arg, *pat;
  171.  
  172. {
  173.     return(makpat(arg, 0, EOS, pat));
  174. }
  175.  
  176. /* amatch (non-recursive) - look for match starting at lin(from) */
  177. amatch(lin, from, pat, sub, maxsub)
  178. char    lin[], pat[], sub[10][MAXPAT];
  179. int    from, maxsub;
  180.  
  181. {
  182.     int    i, j, offset, stack, bgn[10], lst[10], l;
  183.  
  184.     stack = 0;
  185.     offset = from;
  186.     for (j = 0; pat[j] != EOS; j += patsiz(pat, j))
  187.         if (pat[j] == BPAT )
  188.             bgn[pat[j+1]-'0'] = offset;
  189.         else if (pat[j] == EPAT)
  190.             lst[pat[j+1]-'0'] = offset-1;
  191.         else if (pat[j] == CLOSURE) {
  192.             stack = j;
  193.             j += CLOSIZE;
  194.             for (i = offset; lin[i] != EOS; )
  195.                 if (omatch(lin, &i, pat, j) == NO)
  196.                     break;
  197.             pat[stack + COUNT] = i - offset;
  198.             pat[stack + START] = offset;
  199.             offset = i;
  200.             }
  201.         else if (omatch(lin, &offset, pat, j) == NO) {
  202.             for ( ; stack > 0; stack = pat[stack + PREVCL] ) {
  203.                 if (pat[stack + COUNT] > 0)
  204.                     break;
  205.                 }
  206.             if (stack <= 0)
  207.                 return(ERROR);
  208.             pat[stack + COUNT]--;
  209.             j = stack + CLOSIZE;
  210.             offset = pat[stack + START] + pat[stack + COUNT];
  211.             }
  212.     for (l = 1; l <= maxsub; l++)
  213.         copysub(lin, bgn[l], lst[l], sub[l]);
  214.     return(offset);
  215. }
  216.  
  217.  
  218. /* patsiz - returns size of pattern entry at pat(n) */
  219. patsiz(pat, n)
  220. char    pat[];
  221. int    n;
  222.  
  223. {
  224.     switch (pat[n]) {
  225.         case BPAT :
  226.         case EPAT :
  227.         case CHAR :
  228.               return(2);
  229.         case BOL :
  230.         case EOL :
  231.         case ANY :
  232.               return(1);
  233.         case CCL :
  234.         case NCCL:
  235.               return (pat[n+1] + 2);
  236.         case CLOSURE :
  237.               return CLOSIZE;
  238.         default  :
  239.               error("Error in patsiz: can't happen.\n");
  240.     }
  241. }
  242.  
  243.  
  244. /* omatch - try to match a single pattern at pat(j) */
  245. omatch(lin, i, pat, j)
  246. char    lin[], pat[];
  247. int    *i, j;
  248.  
  249. {
  250.     int    bump;
  251.     char    c;
  252.  
  253.     c = lin[*i];
  254.     if (c == EOS)
  255.         return(NO);
  256.     bump = -1;
  257.     switch (pat[j]) {
  258.         case BPAT :
  259.         case EPAT : return(YES);
  260.         case CHAR : if (c == pat[j+1])
  261.                 bump= 1;
  262.                 break;
  263.         case BOL :  if (*i == 0)
  264.                 bump = 0;
  265.                 break;
  266.         case ANY :  if (c != NEWLINE)
  267.                 bump = 1;
  268.                 break;
  269.         case EOL :  if (c == NEWLINE)
  270.                 bump = 0;
  271.                 break;
  272.         case CCL :  if (locate(c, pat, j+1) == YES)
  273.                 bump = 1;
  274.                 break;
  275.         case NCCL:  if (c != NEWLINE && locate(c, pat, j+1) == NO)
  276.                 bump = 1;
  277.                 break;
  278.         default  :  remark("Error in omatch: can't happen.\n");
  279.     }
  280.     if (bump >= 0) {
  281.         *i += bump;
  282.         return(YES);
  283.         }
  284.     return(NO);
  285. }
  286.  
  287. /* locate - look for c in char class at pat(offset) */
  288. locate(c, pat, offset)
  289. char    c, pat[];
  290. int    offset;
  291.  
  292. {
  293.     int    i;
  294.  
  295.     for (i = offset + pat[offset]; i > offset; i--)
  296.         if (c == pat[i])  return YES;
  297.     return NO;
  298. }
  299.  
  300. /* copysub - copy line to sub from b to e */ 
  301. copysub(lin, b, e, sub)
  302. char    lin[], *sub;
  303. int    b, e;
  304. {
  305.     for( ; b <= e; b++)
  306.         *sub++ = lin[b];
  307.     *sub = EOS;
  308.     return;
  309. }
  310.