[BACK]Return to roff.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/roff.c between version 1.374 and 1.375

version 1.374, 2020/04/08 11:56:03 version 1.375, 2020/08/03 11:02:57
Line 192  static int   roff_cc(ROFF_ARGS);
Line 192  static int   roff_cc(ROFF_ARGS);
 static  int              roff_ccond(struct roff *, int, int);  static  int              roff_ccond(struct roff *, int, int);
 static  int              roff_char(ROFF_ARGS);  static  int              roff_char(ROFF_ARGS);
 static  int              roff_cond(ROFF_ARGS);  static  int              roff_cond(ROFF_ARGS);
   static  int              roff_cond_checkend(ROFF_ARGS);
 static  int              roff_cond_text(ROFF_ARGS);  static  int              roff_cond_text(ROFF_ARGS);
 static  int              roff_cond_sub(ROFF_ARGS);  static  int              roff_cond_sub(ROFF_ARGS);
 static  int              roff_ds(ROFF_ARGS);  static  int              roff_ds(ROFF_ARGS);
Line 2034  roff_parse(struct roff *r, char *buf, int *pos, int ln
Line 2035  roff_parse(struct roff *r, char *buf, int *pos, int ln
   
 /* --- handling of request blocks ----------------------------------------- */  /* --- handling of request blocks ----------------------------------------- */
   
   /*
    * Close a macro definition block or an "ignore" block.
    */
 static int  static int
 roff_cblock(ROFF_ARGS)  roff_cblock(ROFF_ARGS)
 {  {
           int      rr;
   
         /*  
          * A block-close `..' should only be invoked as a child of an  
          * ignore macro, otherwise raise a warning and just ignore it.  
          */  
   
         if (r->last == NULL) {          if (r->last == NULL) {
                 mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");                  mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");
                 return ROFF_IGN;                  return ROFF_IGN;
Line 2050  roff_cblock(ROFF_ARGS)
Line 2050  roff_cblock(ROFF_ARGS)
   
         switch (r->last->tok) {          switch (r->last->tok) {
         case ROFF_am:          case ROFF_am:
                 /* ROFF_am1 is remapped to ROFF_am in roff_block(). */  
         case ROFF_ami:          case ROFF_ami:
         case ROFF_de:          case ROFF_de:
                 /* ROFF_de1 is remapped to ROFF_de in roff_block(). */  
         case ROFF_dei:          case ROFF_dei:
         case ROFF_ig:          case ROFF_ig:
                 break;                  break;
           case ROFF_am1:
           case ROFF_de1:
                   /* Remapped in roff_block(). */
                   abort();
         default:          default:
                 mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");                  mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");
                 return ROFF_IGN;                  return ROFF_IGN;
         }          }
   
           roffnode_pop(r);
           roffnode_cleanscope(r);
   
           /*
            * If a conditional block with braces is still open,
            * check for "\}" block end markers.
            */
   
           if (r->last != NULL && r->last->endspan < 0) {
                   rr = 1;  /* If arguments follow "\}", warn about them. */
                   roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
           }
   
         if (buf->buf[pos] != '\0')          if (buf->buf[pos] != '\0')
                 mandoc_msg(MANDOCERR_ARG_SKIP, ln, pos,                  mandoc_msg(MANDOCERR_ARG_SKIP, ln, pos,
                     ".. %s", buf->buf + pos);                      ".. %s", buf->buf + pos);
   
         roffnode_pop(r);  
         roffnode_cleanscope(r);  
         return ROFF_IGN;          return ROFF_IGN;
   
 }  }
   
 /*  /*
Line 2082  roffnode_cleanscope(struct roff *r)
Line 2094  roffnode_cleanscope(struct roff *r)
         int inloop;          int inloop;
   
         inloop = 0;          inloop = 0;
         while (r->last != NULL) {          while (r->last != NULL && r->last->endspan > 0) {
                 if (--r->last->endspan != 0)                  if (--r->last->endspan != 0)
                         break;                          break;
                 inloop += roffnode_pop(r);                  inloop += roffnode_pop(r);
Line 2091  roffnode_cleanscope(struct roff *r)
Line 2103  roffnode_cleanscope(struct roff *r)
 }  }
   
 /*  /*
  * Handle the closing \} of a conditional block.   * Handle the closing "\}" of a conditional block.
  * Apart from generating warnings, this only pops nodes.   * Apart from generating warnings, this only pops nodes.
  * Return the number of loops ended.   * Return the number of loops ended.
  */   */
Line 2311  roff_block_text(ROFF_ARGS)
Line 2323  roff_block_text(ROFF_ARGS)
         return ROFF_IGN;          return ROFF_IGN;
 }  }
   
   /*
    * Check for a closing "\}" and handle it.
    * In this function, the final "int *offs" argument is used for
    * different purposes than elsewhere:
    * Input: *offs == 0: caller wants to discard arguments following \}
    *        *offs == 1: caller wants to preserve text following \}
    * Output: *offs = 0: tell caller to discard input line
    *         *offs = 1: tell caller to use input line
    */
 static int  static int
 roff_cond_sub(ROFF_ARGS)  roff_cond_checkend(ROFF_ARGS)
 {  {
         struct roffnode *bl;  
         char            *ep;          char            *ep;
         int              endloop, irc, rr;          int              endloop, irc, rr;
         enum roff_tok    t;  
   
         irc = ROFF_IGN;          irc = ROFF_IGN;
         rr = r->last->rule;          rr = r->last->rule;
Line 2327  roff_cond_sub(ROFF_ARGS)
Line 2346  roff_cond_sub(ROFF_ARGS)
                 irc |= endloop;                  irc |= endloop;
   
         /*          /*
          * If `\}' occurs on a macro line without a preceding macro,           * If "\}" occurs on a macro line without a preceding macro or
          * drop the line completely.           * a text line contains nothing else, drop the line completely.
          */           */
   
         ep = buf->buf + pos;          ep = buf->buf + pos;
         if (ep[0] == '\\' && ep[1] == '}')          if (ep[0] == '\\' && ep[1] == '}' && (ep[2] == '\0' || *offs == 0))
                 rr = 0;                  rr = 0;
   
         /*          /*
          * The closing delimiter `\}' rewinds the conditional scope           * The closing delimiter "\}" rewinds the conditional scope
          * but is otherwise ignored when interpreting the line.           * but is otherwise ignored when interpreting the line.
          */           */
   
         while ((ep = strchr(ep, '\\')) != NULL) {          while ((ep = strchr(ep, '\\')) != NULL) {
                 switch (ep[1]) {                  switch (ep[1]) {
                 case '}':                  case '}':
                         memmove(ep, ep + 2, strlen(ep + 2) + 1);                          if (rr)
                                   ep[1] = '&';
                           else
                                   memmove(ep, ep + 2, strlen(ep + 2) + 1);
                         if (roff_ccond(r, ln, ep - buf->buf))                          if (roff_ccond(r, ln, ep - buf->buf))
                                 irc |= endloop;                                  irc |= endloop;
                         break;                          break;
Line 2355  roff_cond_sub(ROFF_ARGS)
Line 2377  roff_cond_sub(ROFF_ARGS)
                         break;                          break;
                 }                  }
         }          }
           *offs = rr;
           return irc;
   }
   
   /*
    * Parse and process a request or macro line in conditional scope.
    */
   static int
   roff_cond_sub(ROFF_ARGS)
   {
           struct roffnode *bl;
           int              irc, rr;
           enum roff_tok    t;
   
           rr = 0;  /* If arguments follow "\}", skip them. */
           irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
         t = roff_parse(r, buf->buf, &pos, ln, ppos);          t = roff_parse(r, buf->buf, &pos, ln, ppos);
   
         /* For now, let high level macros abort .ce mode. */          /* For now, let high level macros abort .ce mode. */
Line 2392  roff_cond_sub(ROFF_ARGS)
Line 2429  roff_cond_sub(ROFF_ARGS)
         return irc;          return irc;
 }  }
   
   /*
    * Parse and process a text line in conditional scope.
    */
 static int  static int
 roff_cond_text(ROFF_ARGS)  roff_cond_text(ROFF_ARGS)
 {  {
         char            *ep;          int      irc, rr;
         int              endloop, irc, rr;  
   
         irc = ROFF_IGN;          rr = 1;  /* If arguments follow "\}", preserve them. */
         rr = r->last->rule;          irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
         endloop = tok != ROFF_while ? ROFF_IGN :  
             rr ? ROFF_LOOPCONT : ROFF_LOOPEXIT;  
         if (roffnode_cleanscope(r))  
                 irc |= endloop;  
   
         /*  
          * If `\}' occurs on a text line with neither preceding  
          * nor following characters, drop the line completely.  
          */  
   
         ep = buf->buf + pos;  
         if (strcmp(ep, "\\}") == 0)  
                 rr = 0;  
   
         /*  
          * The closing delimiter `\}' rewinds the conditional scope  
          * but is otherwise ignored when interpreting the line.  
          */  
   
         while ((ep = strchr(ep, '\\')) != NULL) {  
                 switch (ep[1]) {  
                 case '}':  
                         memmove(ep, ep + 2, strlen(ep + 2) + 1);  
                         if (roff_ccond(r, ln, ep - buf->buf))  
                                 irc |= endloop;  
                         break;  
                 case '\0':  
                         ++ep;  
                         break;  
                 default:  
                         ep += 2;  
                         break;  
                 }  
         }  
         if (rr)          if (rr)
                 irc |= ROFF_CONT;                  irc |= ROFF_CONT;
         return irc;          return irc;

Legend:
Removed from v.1.374  
changed lines
  Added in v.1.375

CVSweb