home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / sed-3.02 / sed / compile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-26  |  24.4 KB  |  1,038 lines

  1. /*  GNU SED, a batch stream editor.
  2.     Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1998
  3.     Free Software Foundation, Inc.
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  18.  
  19. /* compile.c: translate sed source into internal form */
  20.  
  21. #include "config.h"
  22. #include <stdio.h>
  23.  
  24. #ifndef __STRICT_ANSI__
  25. # define _GNU_SOURCE
  26. #endif
  27. #include <ctype.h>
  28.  
  29. #ifndef HAVE_STRING_H
  30. # include <strings.h>
  31. # ifdef HAVE_MEMORY_H
  32. #  include <memory.h>
  33. # endif
  34. #else
  35. # include <string.h>
  36. #endif /* HAVE_STRING_H */
  37.  
  38. #ifdef HAVE_STDLIB_H
  39. # include <stdlib.h>
  40. #endif
  41.  
  42. #ifdef HAVE_SYS_TYPES_H
  43. # include <sys/types.h>
  44. #endif
  45. #include "regex-sed.h"
  46. #include "basicdefs.h"
  47. #include "utils.h"
  48. #include "sed.h"
  49.  
  50.  
  51. extern flagT rx_testing;
  52. extern flagT no_default_output;
  53. extern flagT use_extended_syntax_p;
  54.  
  55.  
  56. #define YMAP_LENGTH        256 /*XXX shouldn't this be (UCHAR_MAX+1)?*/
  57. #define VECTOR_ALLOC_INCREMENT    40
  58.  
  59. struct prog_info {
  60.   /* When we're reading a script command from a string, 'prog.base'
  61.      points to the first character in the string, 'prog.cur' points
  62.      to the current character in the string, and 'prog.end' points
  63.      to the end of the string.  This allows us to compile script
  64.      strings that contain nulls, which might happen if we're mmap'ing
  65.      a file. */
  66.   VOID *base;
  67.   const unsigned char *cur;
  68.   const unsigned char *end;
  69.  
  70.   /* This is the current script file.  If it is NULL, we are reading
  71.      from a string stored at 'prog.cur' instead.  If both 'prog.file'
  72.      and 'prog.cur' are NULL, we're in trouble! */
  73.   FILE *file;
  74. };
  75.  
  76. /* Information used to give out useful and informative error messages. */
  77. struct error_info {
  78.   /* This is the name of the current script file. */
  79.   const char *name;
  80.  
  81.   /* This is the number of the current script line that we're compiling. */
  82.   countT line;
  83.  
  84.   /* This is the index of the "-e" expressions on the command line. */
  85.   countT string_expr_count;
  86. };
  87.  
  88.  
  89. static struct vector *compile_program P_((struct vector *));
  90. static struct vector *new_vector
  91.     P_((struct error_info *errinfo, struct vector *old_vector));
  92. static void read_text P_((struct text_buf *buf, int leadin_ch));
  93. static struct sed_cmd *next_cmd_entry P_((struct vector **vectorp));
  94. static int add_then_next P_((struct buffer *b, int ch));
  95. static int snarf_char_class P_((struct buffer *b));
  96. static struct buffer *match_slash P_((int slash, flagT regex, flagT keep_back));
  97. static regex_t *compile_regex P_((struct buffer *b, flagT icase, flagT nosub));
  98. static flagT compile_address P_((struct addr *addr, int ch));
  99. static void compile_filename P_((flagT readit, const char **name, FILE **fp));
  100. static struct sed_label *setup_jump
  101.     P_((struct sed_label *list, struct sed_cmd *cmd, struct vector *vec));
  102. static flagT mark_subst_opts P_((struct subst *cmd));
  103. static int inchar P_((void));
  104. static int in_nonblank P_((void));
  105. static countT in_integer P_((int ch));
  106. static void savchar P_((int ch));
  107. static void bad_prog P_((const char *why));
  108.  
  109.  
  110. /* Where we are in the processing of the input. */
  111. static struct prog_info prog;
  112. static struct error_info cur_input;
  113.  
  114. /* Information about labels and jumps-to-labels.  This is used to do
  115.    the required backpatching after we have compiled all the scripts. */
  116. static struct sed_label *jumps = NULL;
  117. static struct sed_label *labels = NULL;
  118.  
  119. /* We wish to detect #n magic only in the first input argument;
  120.    this flag tracks when we have consumed the first file of input. */
  121. static flagT first_script = 1;
  122.  
  123. /* Allow for scripts like "sed -e 'i\' -e foo": */
  124. static struct buffer *pending_text = NULL;
  125. static struct text_buf *old_text_buf = NULL;
  126.  
  127. /* Various error messages we may want to print */
  128. static const char ONE_ADDR[] = "Command only uses one address";
  129. static const char NO_ADDR[] = "Command doesn't take any addresses";
  130. static const char LINE_JUNK[] = "Extra characters after command";
  131. static const char BAD_EOF[] = "Unexpected End-of-file";
  132. static const char BAD_REGEX_FMT[] = "bad regexp: %s\n";
  133. static const char EXCESS_OPEN_BRACKET[] = "Unmatched `{'";
  134. static const char EXCESS_CLOSE_BRACKET[] = "Unexpected `}'";
  135. static const char NO_REGEX[] = "No previous regular expression";
  136. static const char NO_COMMAND[] = "Missing command";
  137. static const char UNTERM_S_CMD[] = "Unterminated `s' command";
  138. static const char UNTERM_Y_CMD[] = "Unterminated `y' command";
  139.  
  140.  
  141. /* This structure tracks files opened by the 'r', 'w', and 's///w' commands
  142.    so that they may all be closed cleanly at normal program termination.  */
  143. struct fp_list {
  144.     char *name;
  145.     FILE *fp;
  146.     flagT readit_p;
  147.     struct fp_list *link;
  148.   };
  149. static struct fp_list *file_ptrs = NULL;
  150.  
  151. void
  152. close_all_files()
  153. {
  154.   struct fp_list *p, *q;
  155.  
  156.   for (p=file_ptrs; p; p=q)
  157.     {
  158.       if (p->fp)
  159.     ck_fclose(p->fp);
  160.       FREE(p->name);
  161.       q = p->link;
  162.       FREE(p);
  163.     }
  164.   file_ptrs = NULL;
  165. }
  166.  
  167. /* 'str' is a string (from the command line) that contains a sed command.
  168.    Compile the command, and add it to the end of 'cur_program'. */
  169. struct vector *
  170. compile_string(cur_program, str)
  171.   struct vector *cur_program;
  172.   char *str;
  173. {
  174.   static countT string_expr_count = 0;
  175.   struct vector *ret;
  176.  
  177.   prog.file = NULL;
  178.   prog.base = VCAST(VOID *)str;
  179.   prog.cur = CAST(unsigned char *)str;
  180.   prog.end = prog.cur + strlen(str);
  181.  
  182.   cur_input.line = 0;
  183.   cur_input.name = NULL;
  184.   cur_input.string_expr_count = ++string_expr_count;
  185.  
  186.   ret = compile_program(cur_program);
  187.   prog.base = NULL;
  188.   prog.cur = NULL;
  189.   prog.end = NULL;
  190.  
  191.   first_script = 0;
  192.   return ret;
  193. }
  194.  
  195. /* 'cmdfile' is the name of a file containing sed commands.
  196.    Read them in and add them to the end of 'cur_program'.
  197.  */
  198. struct vector *
  199. compile_file(cur_program, cmdfile)
  200.   struct vector *cur_program;
  201.   const char *cmdfile;
  202. {
  203.   size_t len;
  204.   struct vector *ret;
  205.  
  206.   prog.base = NULL;
  207.   prog.cur = NULL;
  208.   prog.end = NULL;
  209.   prog.file = stdin;
  210.   if (cmdfile[0] != '-' || cmdfile[1] != '\0')
  211.     prog.file = ck_fopen(cmdfile, "r");
  212.   if (map_file(prog.file, &prog.base, &len))
  213.     {
  214.       prog.cur = VCAST(const unsigned char *)prog.base;
  215.       prog.end = prog.cur + len;
  216.     }
  217.  
  218.   cur_input.line = 1;
  219.   cur_input.name = cmdfile;
  220.   cur_input.string_expr_count = 0;
  221.  
  222.   ret = compile_program(cur_program);
  223.   if (prog.base)
  224.     {
  225.       unmap_file(prog.base, len);
  226.       prog.base = NULL;
  227.       prog.cur = NULL;
  228.       prog.end = NULL;
  229.     }
  230.   if (prog.file != stdin)
  231.     ck_fclose(prog.file);
  232.   prog.file = NULL;
  233.  
  234.   first_script = 0;
  235.   return ret;
  236. }
  237.  
  238. /* Make any checks which require the whole program to have been read.
  239.    In particular: this backpatches the jump targets.
  240.    Any cleanup which can be done after these checks is done here also.  */
  241. void
  242. check_final_program(program)
  243.   struct vector *program;
  244. {
  245.   struct sed_label *go;
  246.   struct sed_label *lbl;
  247.   struct sed_label *nxt;
  248.  
  249.   /* do all "{"s have a corresponding "}"? */
  250.   if (program->return_v)
  251.     {
  252.       cur_input = *program->return_v->err_info; /* for error reporting */
  253.       bad_prog(EXCESS_OPEN_BRACKET);
  254.     }
  255.   FREE(program->err_info);    /* no longer need this */
  256.   program->err_info = NULL;
  257.  
  258.   /* was the final command an unterminated a/c/i command? */
  259.   if (pending_text)
  260.     {
  261.       old_text_buf->text_len = size_buffer(pending_text);
  262.       old_text_buf->text = MEMDUP(get_buffer(pending_text),
  263.                   old_text_buf->text_len, char);
  264.       free_buffer(pending_text);
  265.       pending_text = NULL;
  266.     }
  267.  
  268.   for (go = jumps; go; go = nxt)
  269.     {
  270.       for (lbl = labels; lbl; lbl = lbl->next)
  271.     if (strcmp(lbl->name, go->name) == 0)
  272.       break;
  273.       if (*go->name && !lbl)
  274.     panic("Can't find label for jump to '%s'", go->name);
  275.       go->v->v[go->v_index].x.jump = lbl;
  276.       nxt = go->next;
  277.       FREE(go->name);
  278.       FREE(go);
  279.     }
  280.   jumps = NULL;
  281.  
  282.   for (lbl = labels; lbl; lbl = lbl->next)
  283.     {
  284.       FREE(lbl->name);
  285.       lbl->name = NULL;
  286.     }
  287. }
  288.  
  289. static struct vector *
  290. new_vector(errinfo, old_vector)
  291.   struct error_info *errinfo;
  292.   struct vector *old_vector;
  293. {
  294.   struct vector *vector = MALLOC(1, struct vector);
  295.   vector->v = NULL;
  296.   vector->v_allocated = 0;
  297.   vector->v_length = 0;
  298.   vector->err_info = MEMDUP(errinfo, 1, struct error_info);
  299.   vector->return_v = old_vector;
  300.   vector->return_i = old_vector ? old_vector->v_length : 0;
  301.   return vector;
  302. }
  303.  
  304. static void
  305. read_text(buf, leadin_ch)
  306.   struct text_buf *buf;
  307.   int leadin_ch;
  308. {
  309.   int ch;
  310.  
  311.   /* Should we start afresh (as opposed to continue a partial text)? */
  312.   if (buf)
  313.     {
  314.       if (pending_text)
  315.     free_buffer(pending_text);
  316.       pending_text = init_buffer();
  317.       buf->text = NULL;
  318.       buf->text_len = 0;
  319.       old_text_buf = buf;
  320.     }
  321.   /* assert(old_text_buf != NULL); */
  322.  
  323.   if (leadin_ch == EOF)
  324.     return;
  325.   while ((ch = inchar()) != EOF && ch != '\n')
  326.     {
  327.       if (ch == '\\')
  328.     {
  329.       if ((ch = inchar()) == EOF)
  330.         {
  331.           add1_buffer(pending_text, '\n');
  332.           return;
  333.         }
  334.     }
  335.       add1_buffer(pending_text, ch);
  336.     }
  337.   add1_buffer(pending_text, '\n');
  338.  
  339.   if (!buf)
  340.     buf = old_text_buf;
  341.   buf->text_len = size_buffer(pending_text);
  342.   buf->text = MEMDUP(get_buffer(pending_text), buf->text_len, char);
  343.   free_buffer(pending_text);
  344.   pending_text = NULL;
  345. }
  346.  
  347.  
  348. /* Read a program (or a subprogram within '{' '}' pairs) in and store
  349.    the compiled form in *'vector'.  Return a pointer to the new vector.  */
  350. static struct vector *
  351. compile_program(vector)
  352.   struct vector *vector;
  353. {
  354.   struct sed_cmd *cur_cmd;
  355.   struct buffer *b;
  356.   struct buffer *b2;
  357.   unsigned char *ustring;
  358.   size_t len;
  359.   int slash;
  360.   int ch;
  361.  
  362.   if (!vector)
  363.     vector = new_vector(&cur_input, NULL);
  364.   if (pending_text)
  365.     read_text(NULL, '\n');
  366.  
  367.   for (;;)
  368.     {
  369.       while ((ch=inchar()) == ';' || ISSPACE(ch))
  370.     ;
  371.       if (ch == EOF)
  372.     break;
  373.  
  374.       cur_cmd = next_cmd_entry(&vector);
  375.       if (compile_address(&cur_cmd->a1, ch))
  376.     {
  377.       ch = in_nonblank();
  378.       if (ch == ',')
  379.         {
  380.           if (!compile_address(&cur_cmd->a2, in_nonblank()))
  381.         bad_prog("Unexpected ','");
  382.           ch = in_nonblank();
  383.         }
  384.     }
  385.       if (cur_cmd->a2.addr_type == addr_is_num
  386.       && cur_cmd->a1.addr_type == addr_is_num
  387.       && cur_cmd->a2.a.addr_number < cur_cmd->a1.a.addr_number)
  388.     cur_cmd->a2.a.addr_number = cur_cmd->a1.a.addr_number;
  389.       if (ch == '!')
  390.     {
  391.       cur_cmd->addr_bang = 1;
  392.       ch = in_nonblank();
  393.       if (ch == '!')
  394.         bad_prog("Multiple '!'s");
  395.     }
  396.  
  397.       cur_cmd->cmd = ch;
  398.       switch (ch)
  399.     {
  400.     case '#':
  401.       if (cur_cmd->a1.addr_type != addr_is_null)
  402.         bad_prog(NO_ADDR);
  403.       ch = inchar();
  404.       if (ch=='n' && first_script && cur_input.line < 2)
  405.         if (   (prog.base && prog.cur==2+CAST(unsigned char *)prog.base)
  406.             || (prog.file && !prog.base && 2==ftell(prog.file)))
  407.           no_default_output = 1;
  408.       while (ch != EOF && ch != '\n')
  409.         ch = inchar();
  410.       continue;    /* restart the for (;;) loop */
  411.  
  412.     case '{':
  413.       ++vector->v_length;    /* be sure to count this insn */
  414.       vector = cur_cmd->x.sub = new_vector(&cur_input, vector);
  415.       continue;    /* restart the for (;;) loop */
  416.  
  417.     case '}':
  418.       /* a return insn for subprograms -t */
  419.       if (!vector->return_v)
  420.         bad_prog(EXCESS_CLOSE_BRACKET);
  421.       if (cur_cmd->a1.addr_type != addr_is_null)
  422.         bad_prog(/*{*/ "} doesn't want any addresses");
  423.       ch = in_nonblank();
  424.       if (ch != EOF && ch != '\n' && ch != ';')
  425.         bad_prog(LINE_JUNK);
  426.       ++vector->v_length;        /* we haven't counted this insn yet */
  427.       FREE(vector->err_info);    /* no longer need this */
  428.       vector->err_info = NULL;
  429.       vector = vector->return_v;
  430.       continue;    /* restart the for (;;) loop */
  431.  
  432.     case 'a':
  433.     case 'i':
  434.       if (cur_cmd->a2.addr_type != addr_is_null)
  435.         bad_prog(ONE_ADDR);
  436.       /* Fall Through */
  437.     case 'c':
  438.       ch = in_nonblank();
  439.       if (ch != '\\')
  440.         bad_prog(LINE_JUNK);
  441.       ch = inchar();
  442.       if (ch != '\n' && ch != EOF)
  443.         bad_prog(LINE_JUNK);
  444.       read_text(&cur_cmd->x.cmd_txt, ch);
  445.       break;
  446.  
  447.     case ':':
  448.       if (cur_cmd->a1.addr_type != addr_is_null)
  449.         bad_prog(": doesn't want any addresses");
  450.       labels = setup_jump(labels, cur_cmd, vector);
  451.       break;
  452.     case 'b':
  453.     case 't':
  454.       jumps = setup_jump(jumps, cur_cmd, vector);
  455.       break;
  456.  
  457.     case 'q':
  458.     case '=':
  459.       if (cur_cmd->a2.addr_type != addr_is_null)
  460.         bad_prog(ONE_ADDR);
  461.       /* Fall Through */
  462.     case 'd':
  463.     case 'D':
  464.     case 'g':
  465.     case 'G':
  466.     case 'h':
  467.     case 'H':
  468.     case 'l':
  469.     case 'n':
  470.     case 'N':
  471.     case 'p':
  472.     case 'P':
  473.     case 'x':
  474.       ch = in_nonblank();
  475.       if (ch != EOF && ch != '\n' && ch != ';')
  476.         bad_prog(LINE_JUNK);
  477.       break;
  478.  
  479.     case 'r':
  480.       if (cur_cmd->a2.addr_type != addr_is_null)
  481.         bad_prog(ONE_ADDR);
  482.       compile_filename(1, &cur_cmd->x.rfile, NULL);
  483.       break;
  484.     case 'w':
  485.       compile_filename(0, NULL, &cur_cmd->x.wfile);
  486.       break;
  487.  
  488.     case 's':
  489.       slash = inchar();
  490.       if ( !(b  = match_slash(slash, 1, 1)) )
  491.         bad_prog(UNTERM_S_CMD);
  492.       if ( !(b2 = match_slash(slash, 0, 1)) )
  493.         bad_prog(UNTERM_S_CMD);
  494.  
  495.       cur_cmd->x.cmd_regex.replace_length = size_buffer(b2);
  496.       cur_cmd->x.cmd_regex.replacement = MEMDUP(get_buffer(b2),
  497.                     cur_cmd->x.cmd_regex.replace_length, char);
  498.       free_buffer(b2);
  499.  
  500.       {
  501.         flagT caseless = mark_subst_opts(&cur_cmd->x.cmd_regex);
  502.         cur_cmd->x.cmd_regex.regx = compile_regex(b, caseless, 0);
  503.       }
  504.       free_buffer(b);
  505.       break;
  506.  
  507.     case 'y':
  508.       ustring = MALLOC(YMAP_LENGTH, unsigned char);
  509.       for (len = 0; len < YMAP_LENGTH; len++)
  510.         ustring[len] = len;
  511.       cur_cmd->x.translate = ustring;
  512.  
  513.       slash = inchar();
  514.       if ( !(b = match_slash(slash, 0, 0)) )
  515.         bad_prog(UNTERM_Y_CMD);
  516.       ustring = CAST(unsigned char *)get_buffer(b);
  517.       for (len = size_buffer(b); len; --len)
  518.         {
  519.           ch = inchar();
  520.           if (ch == slash)
  521.         bad_prog("strings for y command are different lengths");
  522.           if (ch == '\n')
  523.         bad_prog(UNTERM_Y_CMD);
  524.           if (ch == '\\')
  525.         ch = inchar();
  526.           if (ch == EOF)
  527.         bad_prog(BAD_EOF);
  528.           cur_cmd->x.translate[*ustring++] = ch;
  529.         }
  530.       free_buffer(b);
  531.  
  532.       if (inchar() != slash ||
  533.           ((ch = in_nonblank()) != EOF && ch != '\n' && ch != ';'))
  534.         bad_prog(LINE_JUNK);
  535.       break;
  536.  
  537.     case EOF:
  538.       bad_prog(NO_COMMAND);
  539.       /*NOTREACHED*/
  540.     default:
  541.       {
  542.         static char unknown_cmd[] = "Unknown command: ``_''";
  543.         unknown_cmd[sizeof(unknown_cmd)-4] = ch;
  544.         bad_prog(unknown_cmd);
  545.       }
  546.       /*NOTREACHED*/
  547.     }
  548.  
  549.       /* this is buried down here so that "continue" statements will miss it */
  550.       ++vector->v_length;
  551.     }
  552.   return vector;
  553. }
  554.  
  555. static struct sed_cmd *
  556. next_cmd_entry(vectorp)
  557.   struct vector **vectorp;
  558. {
  559.   struct sed_cmd *cmd;
  560.   struct vector *v;
  561.  
  562.   v = *vectorp;
  563.   if (v->v_length == v->v_allocated)
  564.     {
  565.       v->v_allocated += VECTOR_ALLOC_INCREMENT;
  566.       v->v = REALLOC(v->v, v->v_allocated, struct sed_cmd);
  567.     }
  568.  
  569.   cmd = v->v + v->v_length;
  570.   cmd->a1.addr_type = addr_is_null;
  571.   cmd->a2.addr_type = addr_is_null;
  572.   cmd->a1_matched = 0;
  573.   cmd->addr_bang = 0;
  574.  
  575.   *vectorp  = v;
  576.   return cmd;
  577. }
  578.  
  579.  
  580. /* let's not confuse text editors that have only dumb bracket-matching... */
  581. #define OPEN_BRACKET    '['
  582. #define CLOSE_BRACKET    ']'
  583.  
  584. static int
  585. add_then_next(b, ch)
  586.   struct buffer *b;
  587.   int ch;
  588. {
  589.   add1_buffer(b, ch);
  590.   return inchar();
  591. }
  592.  
  593. static int
  594. snarf_char_class(b)
  595.   struct buffer *b;
  596. {
  597.   int ch;
  598.  
  599.   ch = inchar();
  600.   if (ch == '^')
  601.     ch = add_then_next(b, ch);
  602.   if (ch == CLOSE_BRACKET)
  603.     ch = add_then_next(b, ch);
  604.   while (ch != EOF && ch != '\n' && ch != CLOSE_BRACKET)
  605.     {
  606.       if (ch == OPEN_BRACKET)
  607.     {
  608.       int prev;
  609.       int delim = ch = add_then_next(b, ch);
  610.  
  611.       if (delim != '.'  &&  delim != ':'  &&  delim != '=')
  612.         continue; /* bypass the add_then_next() call at bottom of loop */
  613.       for (prev=ch=add_then_next(b, ch);
  614.           !(ch==CLOSE_BRACKET && prev==delim); ch=add_then_next(b, ch))
  615.         {
  616.           if (ch == EOF || ch == '\n')
  617.         return EOF;
  618.           prev = ch;
  619.         }
  620.     }
  621.       else if (ch == '\\')
  622.     {
  623.       ch = inchar();
  624.       if (ch == EOF)
  625.         break;
  626.       if (ch != 'n' && ch != '\n')
  627.         {
  628.           add1_buffer(b, '\\');
  629.           continue; /* bypass the add_then_next() call at bottom of loop */
  630.         }
  631.       ch = '\n';
  632.     }
  633.       ch = add_then_next(b, ch);
  634.     }
  635.  
  636.   /* ensure that a newline here is an error, not a "slash" match: */
  637.   return ch == '\n' ? EOF : ch;
  638. }
  639.  
  640. static struct buffer *
  641. match_slash(slash, regex, keep_backwhack)
  642.   int slash;
  643.   flagT regex;
  644.   flagT keep_backwhack;
  645. {
  646.   struct buffer *b;
  647.   int ch;
  648.  
  649.   b = init_buffer();
  650.   while ((ch = inchar()) != EOF && ch != '\n' && ch != slash)
  651.     {
  652.       if (ch == '\\')
  653.     {
  654.       ch = inchar();
  655.       if (ch == EOF)
  656.         break;
  657.       else if (ch == 'n' && regex)
  658.         ch = '\n';
  659.       else if (ch != '\n' && (ch != slash || keep_backwhack))
  660.         add1_buffer(b, '\\');
  661.     }
  662.       else if (ch == OPEN_BRACKET && regex)
  663.     {
  664.       add1_buffer(b, ch);
  665.       ch = snarf_char_class(b);
  666.       if (ch != CLOSE_BRACKET)
  667.         break;
  668.     }
  669.       add1_buffer(b, ch);
  670.     }
  671.   if (ch == slash)
  672.     return b;
  673.  
  674.   if (ch == '\n')
  675.     savchar(ch);    /* for proper line number in error report */
  676.   if (regex && rx_testing)
  677.     {
  678.       /* This is slightly bogus.  Sed is noticing an ill-formed regexp,
  679.        * but rx is getting the credit.  Fortunately, this only affects
  680.        * a few spencer tests.
  681.        */
  682.       size_t sz = size_buffer(b);
  683.       char *re_txt;
  684.       add1_buffer(b, '\0');
  685.       re_txt = get_buffer(b);
  686.       if (sz > 0 && re_txt[sz] == '\n')
  687.     re_txt[sz] = '\0';
  688.       printf(BAD_REGEX_FMT, re_txt);
  689.       exit(1);
  690.     }
  691.   free_buffer(b);
  692.   return NULL;
  693. }
  694.  
  695. static regex_t *
  696. compile_regex(b, ignore_case, nosub)
  697.   struct buffer *b;
  698.   flagT ignore_case;
  699.   flagT nosub;
  700. {
  701.   /* ``An empty regular expression is equivalent to the last regular
  702.      expression read'' so we have to keep track of the last regexp read.
  703.      We keep track the _source_ form of the regular expression because
  704.      it is possible for different modifiers to be specified. */
  705.   static char *last_re = NULL;
  706.   regex_t *new_regex = MALLOC(1, regex_t);
  707.   size_t sz;
  708.   int cflags;
  709.   int error;
  710.  
  711.   sz = size_buffer(b);
  712.   if (sz > 0)
  713.     {
  714.       add1_buffer(b, '\0');
  715.       FREE(last_re);
  716.       last_re = ck_strdup(get_buffer(b));
  717.     }
  718.   else if (!last_re)
  719.     bad_prog(NO_REGEX);
  720.  
  721.   cflags = 0;
  722.   if (ignore_case)
  723.     cflags |= REG_ICASE;
  724.   if (nosub)
  725.     cflags |= REG_NOSUB;
  726.   if (use_extended_syntax_p)
  727.     cflags |= REG_EXTENDED;
  728.   if ( (error = regcomp(new_regex, last_re, cflags)) )
  729.     {
  730.       char msg[1000];
  731.       if (rx_testing)
  732.     {
  733.       printf(BAD_REGEX_FMT, last_re);
  734.       exit(1);
  735.     }
  736.       regerror(error, NULL, msg, sizeof msg);
  737.       bad_prog(msg);
  738.   }
  739.  
  740.   return new_regex;
  741. }
  742.  
  743. /* Try to read an address for a sed command.  If it succeeds,
  744.    return non-zero and store the resulting address in *'addr'.
  745.    If the input doesn't look like an address read nothing
  746.    and return zero.  */
  747. static flagT
  748. compile_address(addr, ch)
  749.   struct addr *addr;
  750.   int ch;
  751. {
  752.   if (ISDIGIT(ch))
  753.     {
  754.       countT num = in_integer(ch);
  755.       ch = in_nonblank();
  756. #if 1
  757.       if (ch != '~')
  758.     {
  759.       savchar(ch);
  760.     }
  761.       else
  762.     {
  763.       countT num2 = in_integer(in_nonblank());
  764.       if (num2 > 0)
  765.         {
  766.           addr->addr_type = addr_is_mod;
  767.           addr->a.m.offset = num;
  768.           addr->a.m.modulo = num2;
  769.           return 1;
  770.         }
  771.     }
  772.       addr->addr_type = addr_is_num;
  773.       addr->a.addr_number = num;
  774. #else
  775.       if (ch == '~')
  776.     {
  777.       countT num2 = in_integer(in_nonblank());
  778.       if (num2 == 0)
  779.         bad_prog("Zero step size for ~ addressing is not valid");
  780.       addr->addr_type = addr_is_mod;
  781.       addr->a.m.offset = num;
  782.       addr->a.m.modulo = num2;
  783.     }
  784.       else
  785.     {
  786.       savchar(ch);
  787.       addr->addr_type = addr_is_num;
  788.       addr->a.addr_number = num;
  789.     }
  790. #endif
  791.       return 1;
  792.     }
  793.   else if (ch == '/' || ch == '\\')
  794.     {
  795.       flagT caseless = 0;
  796.       struct buffer *b;
  797.       addr->addr_type = addr_is_regex;
  798.       if (ch == '\\')
  799.     ch = inchar();
  800.       if ( !(b = match_slash(ch, 1, 1)) )
  801.     bad_prog("Unterminated address regex");
  802.       ch = in_nonblank();
  803.       if (ch == 'I')    /* lower case i would break existing programs */
  804.     caseless = 1;
  805.       else
  806.     savchar(ch);
  807.       addr->a.addr_regex = compile_regex(b, caseless, 1);
  808.       free_buffer(b);
  809.       return 1;
  810.     }
  811.   else if (ch == '$')
  812.     {
  813.       addr->addr_type = addr_is_last;
  814.       return 1;
  815.     }
  816.   return 0;
  817. }
  818.  
  819. /* read in a filename for a 'r', 'w', or 's///w' command, and
  820.    update the internal structure about files.  The file is
  821.    opened if it isn't already open in the given mode.  */
  822. static void
  823. compile_filename(readit, name, fp)
  824.   flagT readit;
  825.   const char **name;
  826.   FILE **fp;
  827. {
  828.   struct buffer *b;
  829.   int ch;
  830.   char *file_name;
  831.   struct fp_list *p;
  832.  
  833.   b = init_buffer();
  834.   ch = in_nonblank();
  835.   while (ch != EOF && ch != '\n')
  836.     {
  837.       add1_buffer(b, ch);
  838.       ch = inchar();
  839.     }
  840.   add1_buffer(b, '\0');
  841.   file_name = get_buffer(b);
  842.  
  843.   for (p=file_ptrs; p; p=p->link)
  844.     if (p->readit_p == readit && strcmp(p->name, file_name) == 0)
  845.       break;
  846.  
  847.   if (!p)
  848.     {
  849.       p = MALLOC(1, struct fp_list);
  850.       p->name = ck_strdup(file_name);
  851.       p->readit_p = readit;
  852.       p->fp = NULL;
  853.       if (!readit)
  854.     p->fp = ck_fopen(p->name, "w");
  855.       p->link = file_ptrs;
  856.       file_ptrs = p;
  857.     }
  858.  
  859.   free_buffer(b);
  860.   if (name)
  861.     *name = p->name;
  862.   if (fp)
  863.     *fp = p->fp;
  864. }
  865.  
  866. /* Store a label (or label reference) created by a ':', 'b', or 't'
  867.    command so that the jump to/from the label can be backpatched after
  868.    compilation is complete.  */
  869. static struct sed_label *
  870. setup_jump(list, cmd, vec)
  871.   struct sed_label *list;
  872.   struct sed_cmd *cmd;
  873.   struct vector *vec;
  874. {
  875.   struct sed_label *ret;
  876.   struct buffer *b;
  877.   int ch;
  878.  
  879.   b = init_buffer();
  880.   ch = in_nonblank();
  881.  
  882.   while (ch != EOF && ch != '\n'
  883.      && !ISBLANK(ch) && ch != ';' && ch != /*{*/ '}')
  884.     {
  885.       add1_buffer(b, ch);
  886.       ch = inchar();
  887.     }
  888.   savchar(ch);
  889.   add1_buffer(b, '\0');
  890.   ret = MALLOC(1, struct sed_label);
  891.   ret->name = ck_strdup(get_buffer(b));
  892.   ret->v = vec;
  893.   ret->v_index = cmd - vec->v;
  894.   ret->next = list;
  895.   free_buffer(b);
  896.   return ret;
  897. }
  898.  
  899. static flagT
  900. mark_subst_opts(cmd)
  901.   struct subst *cmd;
  902. {
  903.   flagT caseless = 0;
  904.   int ch;
  905.  
  906.   cmd->global = 0;
  907.   cmd->print = 0;
  908.   cmd->numb = 0;
  909.   cmd->wfile = NULL;
  910.  
  911.   for (;;)
  912.     switch ( (ch = in_nonblank()) )
  913.       {
  914.       case 'i':    /* GNU extension */
  915.       case 'I':    /* GNU extension */
  916.     caseless = 1;
  917.     break;
  918.  
  919.       case 'p':
  920.     cmd->print = 1;
  921.     break;
  922.  
  923.       case 'g':
  924.     cmd->global = 1;
  925.     break;
  926.  
  927.       case 'w':
  928.     compile_filename(0, NULL, &cmd->wfile);
  929.     return caseless;
  930.  
  931.       case '0': case '1': case '2': case '3': case '4':
  932.       case '5': case '6': case '7': case '8': case '9':
  933.     if (cmd->numb)
  934.       bad_prog("multiple number options to 's' command");
  935.     cmd->numb = in_integer(ch);
  936.     if (!cmd->numb)
  937.       bad_prog("number option to 's' command may not be zero");
  938.     break;
  939.  
  940.       case EOF:
  941.       case '\n':
  942.       case ';':
  943.     return caseless;
  944.  
  945.       default:
  946.     bad_prog("Unknown option to 's'");
  947.     /*NOTREACHED*/
  948.       }
  949. }
  950.  
  951.  
  952. /* Read the next character from the program.  Return EOF if there isn't
  953.    anything to read.  Keep cur_input.line up to date, so error messages
  954.    can be meaningful. */
  955. static int
  956. inchar()
  957. {
  958.   int ch = EOF;
  959.  
  960.   if (prog.cur)
  961.     {
  962.       if (prog.cur < prog.end)
  963.     ch = *prog.cur++;
  964.     }
  965.   else if (prog.file)
  966.     {
  967.       if (!feof(prog.file))
  968.     ch = getc(prog.file);
  969.     }
  970.   if (ch == '\n')
  971.     ++cur_input.line;
  972.   return ch;
  973. }
  974.  
  975. /* Read the next non-blank character from the program.  */
  976. static int
  977. in_nonblank()
  978. {
  979.   int ch;
  980.   do
  981.     ch = inchar();
  982.     while (ISBLANK(ch));
  983.   return ch;
  984. }
  985.  
  986. /* Read an integer value from the program.  */
  987. static countT
  988. in_integer(ch)
  989.   int ch;
  990. {
  991.   countT num = 0;
  992.  
  993.   while (ISDIGIT(ch))
  994.     {
  995.       num = num * 10 + ch - '0';
  996.       ch = inchar();
  997.     }
  998.   savchar(ch);
  999.   return num;
  1000. }
  1001.  
  1002. /* unget 'ch' so the next call to inchar will return it.   */
  1003. static void
  1004. savchar(ch)
  1005.   int ch;
  1006. {
  1007.   if (ch == EOF)
  1008.     return;
  1009.   if (ch == '\n' && cur_input.line > 0)
  1010.     --cur_input.line;
  1011.   if (prog.cur)
  1012.     {
  1013.       if (prog.cur <= CAST(const unsigned char *)prog.base
  1014.       || *--prog.cur != ch)
  1015.     panic("Called savchar() with unexpected pushback (%x)",
  1016.           CAST(unsigned char)ch);
  1017.     }
  1018.   else
  1019.     ungetc(ch, prog.file);
  1020. }
  1021.  
  1022. /* Complain about a programming error and exit. */
  1023. static void
  1024. bad_prog(why)
  1025.   const char *why;
  1026. {
  1027.   if (cur_input.name)
  1028.     fprintf(stderr, "%s: file %s line %lu: %s\n",
  1029.         myname, cur_input.name, CAST(unsigned long)cur_input.line, why);
  1030.   else
  1031.     fprintf(stderr, "%s: -e expression #%lu, char %lu: %s\n",
  1032.         myname,
  1033.         CAST(unsigned long)cur_input.string_expr_count,
  1034.         CAST(unsigned long)(prog.cur-CAST(unsigned char *)prog.base),
  1035.         why);
  1036.   exit(1);
  1037. }
  1038.