/[mailutils]/mailutils/mh/mh_format.c
ViewVC logotype

Diff of /mailutils/mh/mh_format.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.25 by gray, Sun Jan 26 13:47:02 2003 UTC revision 1.26 by gray, Fri Jan 31 15:00:06 2003 UTC
# Line 1  Line 1 
1  /* GNU Mailutils -- a suite of utilities for electronic mail  /* GNU Mailutils -- a suite of utilities for electronic mail
2     Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.     Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3    
4     GNU Mailutils is free software; you can redistribute it and/or modify     GNU Mailutils is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 23  Line 23 
23  # include <strings.h>  # include <strings.h>
24  #endif  #endif
25    
26    #define obstack_chunk_alloc malloc
27    #define obstack_chunk_free free
28    #include <obstack.h>
29    
30  typedef struct       /* A string object type */  typedef struct       /* A string object type */
31  {  {
32    int size;          /* Allocated size or 0 for static storage */    int size;          /* Allocated size or 0 for static storage */
# Line 42  struct mh_machine Line 46  struct mh_machine
46    mh_instr_t *prog;         /* Program itself */    mh_instr_t *prog;         /* Program itself */
47    int stop;                 /* Stop execution immediately */    int stop;                 /* Stop execution immediately */
48    
49    char *outbuf;             /* Output buffer */    struct obstack stk;       /* Output buffer */
50    size_t width;             /* Output buffer size */    size_t width;             /* Output buffer width */
51    size_t ind;               /* Output buffer index */    size_t ind;               /* Output buffer index */
52    
53    int fmtflags;             /* Current formatting flags */    int fmtflags;             /* Current formatting flags */
# Line 163  compress_ws (char *str, size_t *size) Line 167  compress_ws (char *str, size_t *size)
167    *size = p - (unsigned char*) str;    *size = p - (unsigned char*) str;
168  }  }
169    
170    static void
171    put_string (struct mh_machine *mach, char *str, int len)
172    {
173      if (len == 0)
174        len = strlen (str);
175      obstack_grow (&mach->stk, str, len);
176      mach->ind += len;
177    }
178    
179    static void
180    print_hdr_segment (struct mh_machine *mach, char *str, size_t len)
181    {
182      if (!len)
183        len = strlen (str);
184    
185      if (len < mach->width)
186        put_string (mach, str, len);
187      else
188        {
189          char *endp = str + len;
190          
191          while (str < endp)
192            {
193              size_t rest;
194              char *p;
195              size_t size;
196              
197              size = endp - str;
198              rest = mach->width - mach->ind;
199              if (size < rest)
200                {
201                  put_string (mach, str, size);
202                  break;
203                }
204              
205              for (p = str + rest - 1; p > str && !isspace (*p); p--)
206                ;
207    
208              if (p > str)
209                {
210                  put_string (mach, str, p - str);
211                  put_string (mach, "\n\t", 0);
212                  mach->ind = 1;
213                  str = p;
214                }
215              else
216                {
217                  put_string (mach, str, size);
218                  str += len;
219                }
220            }
221        }
222    }
223    
224  /* Print len bytes from str into mach->outbuf */  /* Print len bytes from str into mach->outbuf */
225  static void  static void
226  print_string (struct mh_machine *mach, size_t width, char *str, size_t fmtlen)  print_hdr_string (struct mh_machine *mach, char *str)
227  {  {
228    size_t rest, len;    char *p;
229        
230    if (!str)    if (!str)
231      str = "";      str = "";
232    
233      p = strchr (str, '\n');
234      while (p)
235        {
236          print_hdr_segment (mach, str, p - str + 1);
237          mach->ind = 0;
238          str = p + 1;
239          p = strchr (str, '\n');
240        }
241        
242      if (str[0])
243        print_hdr_segment (mach, str, 0);
244    }
245    
246    static void
247    print_simple_segment (struct mh_machine *mach, size_t width,
248                          char *str, size_t len)
249    {
250      size_t rest;
251    
252      if (!str)
253        str = "";
254    
255      if (!len)
256        len = strlen (str);
257    
258    if (!width)    if (!width)
259      width = mach->width;      width = mach->width;
260    len = strlen (str);  
261    rest = width - mach->ind;    rest = width - mach->ind;
262      if (rest == 0)
263        return;
264    if (len > rest)    if (len > rest)
265        len = rest;
266    
267      put_string (mach, str, len);
268    }
269    
270    static void
271    print_string (struct mh_machine *mach, size_t width, char *str)
272    {
273      char *p;
274      
275      if (!str)
276        str = "";
277    
278      if (!width)
279        width = mach->width;
280    
281      p = strchr (str, '\n');
282      while (p)
283      {      {
284        if (fmtlen >= len)        print_simple_segment (mach, width, str, p - str + 1);
285          fmtlen = rest;        mach->ind = 0;
286        len = rest;        str = p + 1;
287          p = strchr (str, '\n');
288      }      }
289        
290      if (str[0])
291        print_simple_segment (mach, width, str, 0);
292    }
293        
294    if (fmtlen < len)  static void
295      len = fmtlen;  print_fmt_string (struct mh_machine *mach, size_t fmtwidth, char *str)
296      {
297    memcpy (mach->outbuf + mach->ind, str, len);    size_t len = strlen (str);
298    mach->ind += len;    if (len > fmtwidth)
299        len = fmtwidth;
300      put_string (mach, str, len);
301    
302    if (fmtlen > len)    if (fmtwidth > len)
303      {      {
304        fmtlen -= len;        fmtwidth -= len;
305        memset (mach->outbuf + mach->ind, ' ', fmtlen);        mach->ind += fmtwidth;
306        mach->ind += fmtlen;        while (fmtwidth--)
307            obstack_1grow (&mach->stk, ' ');
308      }      }
309  }  }
310    
311    /* FIXME: width? */
312  static void  static void
313  print_obj (struct mh_machine *mach, size_t width, strobj_t *obj)  print_obj (struct mh_machine *mach, size_t width, strobj_t *obj)
314  {  {
315    if (!strobj_is_null (obj))    if (!strobj_is_null (obj))
316      print_string (mach, 0, strobj_ptr (obj), strobj_len (obj));      print_string (mach, 0, strobj_ptr (obj));
317  }  }
318    
319  static void  static void
# Line 210  reset_fmt_defaults (struct mh_machine *m Line 322  reset_fmt_defaults (struct mh_machine *m
322    mach->fmtflags = 0;    mach->fmtflags = 0;
323  }  }
324    
325    static void
326    format_num (struct mh_machine *mach, long num)
327    {
328      int n;
329      char buf[64];
330      char *ptr;
331      int fmtwidth = mach->fmtflags & MH_WIDTH_MASK;
332      int padchar = mach->fmtflags & MH_FMT_ZEROPAD ? '0' : ' ';
333                
334      n = snprintf (buf, sizeof buf, "%ld", num);
335    
336      if (fmtwidth)
337        {
338          if (n > fmtwidth)
339            {
340              ptr = buf + n - fmtwidth;
341              *ptr = '?';
342            }
343          else
344            {
345              int i;
346              ptr = buf;
347              for (i = n; i < fmtwidth && mach->ind < mach->width;
348                   i++, mach->ind++)
349                obstack_1grow (&mach->stk, padchar);
350            }
351        }
352      else
353        ptr = buf;
354    
355      print_string (mach, 0, ptr);
356      reset_fmt_defaults (mach);
357    }
358    
359    static void
360    format_str (struct mh_machine *mach, char *str)
361    {
362      if (!str)
363        str = "";
364      if (mach->fmtflags)
365        {
366          int len = strlen (str);
367          int fmtwidth = mach->fmtflags & MH_WIDTH_MASK;
368          int padchar = ' ';
369                                    
370          if (mach->fmtflags & MH_FMT_RALIGN)
371            {
372              int i, n;
373              
374              n = fmtwidth - len;
375              for (i = 0; i < n && mach->ind < mach->width;
376                   i++, mach->ind++, fmtwidth--)
377                obstack_1grow (&mach->stk, padchar);
378            }
379                  
380          print_fmt_string (mach, fmtwidth, str);
381          reset_fmt_defaults (mach);
382        }
383      else
384        print_string (mach, 0, str);
385    }
386    
387  /* Execute pre-compiled format on message msg with number msgno.  /* Execute pre-compiled format on message msg with number msgno.
388     buffer and bufsize specify output storage */     buffer and bufsize specify output storage */
389  int  int
390  mh_format (mh_format_t *fmt, message_t msg, size_t msgno,  mh_format (mh_format_t *fmt, message_t msg, size_t msgno,
391             char *buffer, size_t bufsize)             size_t width, char **pret)
392  {  {
393    struct mh_machine mach;    struct mh_machine mach;
394    char buf[64];    char buf[64];
# Line 226  mh_format (mh_format_t *fmt, message_t m Line 400  mh_format (mh_format_t *fmt, message_t m
400    mach.message = msg;    mach.message = msg;
401    mach.msgno = msgno;    mach.msgno = msgno;
402        
403    mach.width = bufsize - 1;  /* Allow for terminating NULL */    mach.width = width;
   mach.outbuf = buffer;  
404    mach.pc = 1;    mach.pc = 1;
405      obstack_init (&mach.stk);
406    reset_fmt_defaults (&mach);    reset_fmt_defaults (&mach);
407        
408    while (!mach.stop)    while (!mach.stop)
# Line 357  mh_format (mh_format_t *fmt, message_t m Line 531  mh_format (mh_format_t *fmt, message_t m
531            break;            break;
532    
533          case mhop_num_print:          case mhop_num_print:
534            {            format_num (&mach, mach.reg_num);
             int n;  
             char buf[64];  
             char *ptr;  
             int fmtwidth = mach.fmtflags & MH_WIDTH_MASK;  
             int padchar = mach.fmtflags & MH_FMT_ZEROPAD ? '0' : ' ';  
               
             n = snprintf (buf, sizeof buf, "%d", mach.reg_num);  
   
             if (fmtwidth)  
               {  
                 if (n > fmtwidth)  
                   {  
                     ptr = buf + n - fmtwidth;  
                     *ptr = '?';  
                   }  
                 else  
                   {  
                     int i;  
                     ptr = buf;  
                     for (i = n; i < fmtwidth && mach.ind < mach.width;  
                          i++, mach.ind++)  
                       mach.outbuf[mach.ind] = padchar;  
                   }  
               }  
             else  
               ptr = buf;  
   
             print_string (&mach, 0, ptr, strlen (ptr));  
             reset_fmt_defaults (&mach);  
           }  
535            break;            break;
536                        
537          case mhop_str_print:          case mhop_str_print:
538            if (mach.fmtflags)            format_str (&mach, strobj_ptr (&mach.reg_str));
             {  
               int len = strobj_len (&mach.reg_str);  
               int fmtwidth = mach.fmtflags & MH_WIDTH_MASK;  
               int padchar = ' ';  
                                   
               if (mach.fmtflags & MH_FMT_RALIGN)  
                 {  
                   int i, n;  
   
                   n = fmtwidth - len;  
                   for (i = 0; i < n && mach.ind < mach.width;  
                        i++, mach.ind++, fmtwidth--)  
                     mach.outbuf[mach.ind] = padchar;  
                 }  
                   
               print_string (&mach, 0, strobj_ptr (&mach.reg_str), fmtwidth);  
               reset_fmt_defaults (&mach);  
             }  
           else  
             print_obj (&mach, 0, &mach.reg_str);  
539            break;            break;
540    
541          case mhop_fmtspec:          case mhop_fmtspec:
# Line 425  mh_format (mh_format_t *fmt, message_t m Line 549  mh_format (mh_format_t *fmt, message_t m
549      }      }
550    strobj_free (&mach.reg_str);    strobj_free (&mach.reg_str);
551    strobj_free (&mach.arg_str);    strobj_free (&mach.arg_str);
552    mach.outbuf[mach.ind] = 0;  
553      if (pret)
554        {
555          obstack_1grow (&mach.stk, 0);
556          *pret = strdup (obstack_finish (&mach.stk));
557        }
558      obstack_free (&mach.stk, NULL);
559    return mach.ind;    return mach.ind;
560  }  }
561    
# Line 843  builtin_trim (struct mh_machine *mach) Line 973  builtin_trim (struct mh_machine *mach)
973  static void  static void
974  builtin_putstr (struct mh_machine *mach)  builtin_putstr (struct mh_machine *mach)
975  {  {
976    print_string (mach, 0,    print_string (mach, 0, strobj_ptr (&mach->arg_str));
                 strobj_ptr (&mach->arg_str), strobj_len (&mach->arg_str));  
977  }  }
978    
979  /*     putstrf    expr              print str in a fixed width*/  /*     putstrf    expr              print str in a fixed width*/
980  static void  static void
981  builtin_putstrf (struct mh_machine *mach)  builtin_putstrf (struct mh_machine *mach)
982  {  {
983    print_string (mach, mach->reg_num,    format_str (mach, strobj_ptr (&mach->arg_str));
                 strobj_ptr (&mach->arg_str), strobj_len (&mach->arg_str));  
984  }  }
985    
986  /*     putnum     expr              print num*/  /*     putnum     expr              print num*/
# Line 861  builtin_putnum (struct mh_machine *mach) Line 989  builtin_putnum (struct mh_machine *mach)
989  {  {
990    char *p;    char *p;
991    asprintf (&p, "%d", mach->arg_num);    asprintf (&p, "%d", mach->arg_num);
992    print_string (mach, 0, p, strlen (p));    print_string (mach, 0, p);
993    free (p);    free (p);
994  }  }
995    
# Line 869  builtin_putnum (struct mh_machine *mach) Line 997  builtin_putnum (struct mh_machine *mach)
997  static void  static void
998  builtin_putnumf (struct mh_machine *mach)  builtin_putnumf (struct mh_machine *mach)
999  {  {
1000    char *p;    format_num (mach, mach->arg_num);
   asprintf (&p, "%d", mach->arg_num);  
   print_string (mach, mach->reg_num, p, strlen (p));  
   free (p);  
1001  }  }
1002    
1003  static int  static int
# Line 1658  builtin_concat (struct mh_machine *mach) Line 1783  builtin_concat (struct mh_machine *mach)
1783  }  }
1784    
1785  static void  static void
1786  builtin_printstr (struct mh_machine *mach)  builtin_printhdr (struct mh_machine *mach)
1787  {  {
1788    print_obj (mach, mach->reg_num, &mach->arg_str);    if (!strobj_is_null (&mach->arg_str))
1789    print_obj (mach, mach->reg_num, &mach->reg_str);      print_hdr_string (mach, strobj_ptr (&mach->arg_str));
1790      if (!strobj_is_null (&mach->reg_str))
1791        print_hdr_string (mach, strobj_ptr (&mach->reg_str));
1792  }  }
1793    
1794  static void  static void
# Line 1739  mh_builtin_t builtin_tab[] = { Line 1866  mh_builtin_t builtin_tab[] = {
1866    { "comp",     builtin_comp,     mhtype_num,  mhtype_str },    { "comp",     builtin_comp,     mhtype_num,  mhtype_str },
1867    { "compval",  builtin_compval,  mhtype_num,  mhtype_str },    { "compval",  builtin_compval,  mhtype_num,  mhtype_str },
1868    { "trim",     builtin_trim,     mhtype_str,  mhtype_str, 1 },    { "trim",     builtin_trim,     mhtype_str,  mhtype_str, 1 },
1869    { "putstr",   builtin_putstr,   mhtype_str,  mhtype_str, 1 },    { "putstr",   builtin_putstr,   mhtype_none,  mhtype_str, 1 },
1870    { "putstrf",  builtin_putstrf,  mhtype_str,  mhtype_str, 1 },    { "putstrf",  builtin_putstrf,  mhtype_none,  mhtype_str, 1 },
1871    { "putnum",   builtin_putnum,   mhtype_str,  mhtype_num, 1 },    { "putnum",   builtin_putnum,   mhtype_none,  mhtype_num, 1 },
1872    { "putnumf",  builtin_putnumf,  mhtype_str,  mhtype_num, 1 },    { "putnumf",  builtin_putnumf,  mhtype_none,  mhtype_num, 1 },
1873    { "sec",      builtin_sec,      mhtype_num,  mhtype_str },    { "sec",      builtin_sec,      mhtype_num,  mhtype_str },
1874    { "min",      builtin_min,      mhtype_num,  mhtype_str },    { "min",      builtin_min,      mhtype_num,  mhtype_str },
1875    { "hour",     builtin_hour,     mhtype_num,  mhtype_str },    { "hour",     builtin_hour,     mhtype_num,  mhtype_str },
# Line 1785  mh_builtin_t builtin_tab[] = { Line 1912  mh_builtin_t builtin_tab[] = {
1912    { "unre",     builtin_unre,     mhtype_str,  mhtype_str },    { "unre",     builtin_unre,     mhtype_str,  mhtype_str },
1913    { "rcpt",     builtin_rcpt,     mhtype_num,  mhtype_str },    { "rcpt",     builtin_rcpt,     mhtype_num,  mhtype_str },
1914    { "concat",   builtin_concat,   mhtype_none, mhtype_str,     1 },    { "concat",   builtin_concat,   mhtype_none, mhtype_str,     1 },
1915    { "printstr", builtin_printstr, mhtype_none, mhtype_str },    { "printhdr", builtin_printhdr, mhtype_none, mhtype_str },
1916    { "in_reply_to", builtin_in_reply_to, mhtype_str,  mhtype_none },    { "in_reply_to", builtin_in_reply_to, mhtype_str,  mhtype_none },
1917    { "references", builtin_references, mhtype_str,  mhtype_none },    { "references", builtin_references, mhtype_str,  mhtype_none },
1918    { "package",  builtin_package,  mhtype_str, mhtype_none },    { "package",  builtin_package,  mhtype_str, mhtype_none },

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.26

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26