Commit a19e1308 a19e1308f97472a67fb5c1ebe1810bceae59341e by Sergey Poznyakoff

(strobj_is_null,strobj_realloc): New function.

(print_string): Accept an explicit width argument.
(print_obj): New function.
(mh_format): Use the new functions.
(builtin_lit): Fixed.
(builtin_formataddr,builtin_putaddr): Implemented.
1 parent c2520d2f
...@@ -65,6 +65,7 @@ strobj_free (strobj_t *obj) ...@@ -65,6 +65,7 @@ strobj_free (strobj_t *obj)
65 65
66 #define strobj_ptr(p) ((p)->ptr ? (p)->ptr : "") 66 #define strobj_ptr(p) ((p)->ptr ? (p)->ptr : "")
67 #define strobj_len(p) strlen((p)->ptr) 67 #define strobj_len(p) strlen((p)->ptr)
68 #define strobj_is_null(p) ((p)->ptr == NULL)
68 #define strobj_is_static(p) ((p)->size == 0) 69 #define strobj_is_static(p) ((p)->size == 0)
69 70
70 static void 71 static void
...@@ -102,7 +103,9 @@ strobj_assign (strobj_t *lvalue, strobj_t *rvalue) ...@@ -102,7 +103,9 @@ strobj_assign (strobj_t *lvalue, strobj_t *rvalue)
102 static void 103 static void
103 strobj_copy (strobj_t *lvalue, strobj_t *rvalue) 104 strobj_copy (strobj_t *lvalue, strobj_t *rvalue)
104 { 105 {
105 if (lvalue->size >= strobj_len (rvalue) + 1) 106 if (strobj_is_null (rvalue))
107 strobj_free (lvalue);
108 else if (lvalue->size >= strobj_len (rvalue) + 1)
106 memcpy (lvalue->ptr, strobj_ptr (rvalue), strobj_len (rvalue) + 1); 109 memcpy (lvalue->ptr, strobj_ptr (rvalue), strobj_len (rvalue) + 1);
107 else 110 else
108 { 111 {
...@@ -112,6 +115,25 @@ strobj_copy (strobj_t *lvalue, strobj_t *rvalue) ...@@ -112,6 +115,25 @@ strobj_copy (strobj_t *lvalue, strobj_t *rvalue)
112 } 115 }
113 } 116 }
114 117
118 static void
119 strobj_realloc (strobj_t *obj, size_t length)
120 {
121 if (strobj_is_static (obj))
122 {
123 char *value = strobj_ptr (obj);
124 obj->ptr = xmalloc (length);
125 strncpy (obj->ptr, value, length-1);
126 obj->ptr[length-1] = 0;
127 obj->size = length;
128 }
129 else
130 {
131 obj->ptr = xrealloc (obj->ptr, length);
132 obj->ptr[length-1] = 0;
133 obj->size = length;
134 }
135 }
136
115 /* Compress whitespace in a string */ 137 /* Compress whitespace in a string */
116 static void 138 static void
117 compress_ws (char *str, size_t *size) 139 compress_ws (char *str, size_t *size)
...@@ -141,12 +163,14 @@ compress_ws (char *str, size_t *size) ...@@ -141,12 +163,14 @@ compress_ws (char *str, size_t *size)
141 163
142 /* Print len bytes from str into mach->outbuf */ 164 /* Print len bytes from str into mach->outbuf */
143 static void 165 static void
144 print_string (struct mh_machine *mach, char *str, size_t len) 166 print_string (struct mh_machine *mach, size_t width, char *str, size_t len)
145 { 167 {
146 size_t rest = strlen (str); 168 size_t rest = strlen (str);
147 169
148 if (len > rest) 170 if (len > rest)
149 len = rest; 171 len = rest;
172 if (!width)
173 width = mach->width;
150 rest = mach->width - mach->ind; 174 rest = mach->width - mach->ind;
151 if (len > rest) 175 if (len > rest)
152 len = rest; 176 len = rest;
...@@ -155,6 +179,13 @@ print_string (struct mh_machine *mach, char *str, size_t len) ...@@ -155,6 +179,13 @@ print_string (struct mh_machine *mach, char *str, size_t len)
155 } 179 }
156 180
157 static void 181 static void
182 print_obj (struct mh_machine *mach, size_t width, strobj_t *obj)
183 {
184 if (!strobj_is_null (obj))
185 print_string (mach, 0, strobj_ptr (obj), strobj_len (obj));
186 }
187
188 static void
158 reset_fmt_defaults (struct mh_machine *mach) 189 reset_fmt_defaults (struct mh_machine *mach)
159 { 190 {
160 mach->fmtflags = 0; 191 mach->fmtflags = 0;
...@@ -335,7 +366,7 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno, ...@@ -335,7 +366,7 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno,
335 else 366 else
336 ptr = buf; 367 ptr = buf;
337 368
338 print_string (&mach, ptr, strlen (ptr)); 369 print_string (&mach, 0, ptr, strlen (ptr));
339 reset_fmt_defaults (&mach); 370 reset_fmt_defaults (&mach);
340 } 371 }
341 break; 372 break;
...@@ -357,15 +388,11 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno, ...@@ -357,15 +388,11 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno,
357 mach.outbuf[mach.ind] = padchar; 388 mach.outbuf[mach.ind] = padchar;
358 } 389 }
359 390
360 print_string (&mach, strobj_ptr (&mach.reg_str), fmtwidth); 391 print_string (&mach, 0, strobj_ptr (&mach.reg_str), fmtwidth);
361 reset_fmt_defaults (&mach); 392 reset_fmt_defaults (&mach);
362 } 393 }
363 else if (mach.reg_str.ptr) 394 else
364 { 395 print_obj (&mach, 0, &mach.reg_str);
365 print_string (&mach,
366 strobj_ptr (&mach.reg_str),
367 strobj_len (&mach.reg_str));
368 }
369 break; 396 break;
370 397
371 case mhop_fmtspec: 398 case mhop_fmtspec:
...@@ -537,7 +564,7 @@ builtin_num (struct mh_machine *mach) ...@@ -537,7 +564,7 @@ builtin_num (struct mh_machine *mach)
537 static void 564 static void
538 builtin_lit (struct mh_machine *mach) 565 builtin_lit (struct mh_machine *mach)
539 { 566 {
540 strobj_assign (&mach->reg_str, &mach->arg_str); 567 /* do nothing */
541 } 568 }
542 569
543 static void 570 static void
...@@ -648,7 +675,7 @@ _parse_date (struct mh_machine *mach, struct tm *tm, mu_timezone *tz) ...@@ -648,7 +675,7 @@ _parse_date (struct mh_machine *mach, struct tm *tm, mu_timezone *tz)
648 char *date = strobj_ptr (&mach->arg_str); 675 char *date = strobj_ptr (&mach->arg_str);
649 const char *p = date; 676 const char *p = date;
650 677
651 if (parse822_date_time(&p, date+strlen(date), tm, tz)) 678 if (parse822_date_time (&p, date+strlen(date), tm, tz))
652 { 679 {
653 mh_error ("can't parse date: [%s]", date); 680 mh_error ("can't parse date: [%s]", date);
654 return -1; 681 return -1;
...@@ -1201,7 +1228,7 @@ static void ...@@ -1201,7 +1228,7 @@ static void
1201 builtin_formataddr (struct mh_machine *mach) 1228 builtin_formataddr (struct mh_machine *mach)
1202 { 1229 {
1203 address_t addr; 1230 address_t addr;
1204 size_t num = 0, n, i; 1231 size_t num = 0, n, i, length = 0, reglen;
1205 char buf[80], *p; 1232 char buf[80], *p;
1206 1233
1207 if (address_create (&addr, strobj_ptr (&mach->arg_str))) 1234 if (address_create (&addr, strobj_ptr (&mach->arg_str)))
...@@ -1209,19 +1236,35 @@ builtin_formataddr (struct mh_machine *mach) ...@@ -1209,19 +1236,35 @@ builtin_formataddr (struct mh_machine *mach)
1209 address_get_count (addr, &num); 1236 address_get_count (addr, &num);
1210 for (i = 1; i <= num; i++) 1237 for (i = 1; i <= num; i++)
1211 { 1238 {
1239 if (address_get_personal (addr, i, buf, sizeof buf, &n) == 0
1240 && n != 0)
1241 length += n+1; /* + space */
1212 address_get_email (addr, i, buf, sizeof buf, &n); 1242 address_get_email (addr, i, buf, sizeof buf, &n);
1213 num += n+1; 1243 length += n+3; /* two brackets + (eventual) comma */
1214 } 1244 }
1215 1245
1216 num += strobj_len (&mach->reg_str) + 1; 1246 if (strobj_is_null (&mach->reg_str))
1217 mach->reg_str.ptr = xrealloc (mach->reg_str.ptr, num); 1247 reglen = 0;
1218 mach->reg_str.size = num + 1; 1248 else
1219 p = strobj_ptr (&mach->reg_str) + strobj_len (&mach->reg_str) ; 1249 reglen = strobj_len (&mach->reg_str);
1250 length += reglen + 1;
1251 strobj_realloc (&mach->reg_str, length);
1252 p = strobj_ptr (&mach->reg_str) + reglen;
1220 for (i = 1; i <= num; i++) 1253 for (i = 1; i <= num; i++)
1221 { 1254 {
1255 if (reglen > 0)
1256 *p++ = ',';
1257 if (address_get_personal (addr, i, buf, sizeof buf, &n) == 0 && n > 0)
1258 {
1259 memcpy (p, buf, n);
1260 p += n;
1261 *p++ = ' ';
1262 }
1222 address_get_email (addr, i, buf, sizeof buf, &n); 1263 address_get_email (addr, i, buf, sizeof buf, &n);
1264 *p++ = '<';
1223 memcpy (p, buf, n); 1265 memcpy (p, buf, n);
1224 p += n; 1266 p += n;
1267 *p++ = '>';
1225 } 1268 }
1226 *p = 0; 1269 *p = 0;
1227 } 1270 }
...@@ -1232,14 +1275,14 @@ builtin_formataddr (struct mh_machine *mach) ...@@ -1232,14 +1275,14 @@ builtin_formataddr (struct mh_machine *mach)
1232 static void 1275 static void
1233 builtin_putaddr (struct mh_machine *mach) 1276 builtin_putaddr (struct mh_machine *mach)
1234 { 1277 {
1235 /*FIXME:*/ 1278 print_obj (mach, mach->reg_num, &mach->arg_str);
1236 builtin_not_implemented ("putaddr"); 1279 print_obj (mach, mach->reg_num, &mach->reg_str);
1237 } 1280 }
1238 1281
1239 /* Builtin function table */ 1282 /* Builtin function table */
1240 1283
1241 mh_builtin_t builtin_tab[] = { 1284 mh_builtin_t builtin_tab[] = {
1242 /* Name Handling function Return type Arg type */ 1285 /* Name Handling function Return type Arg type Opt. arg */
1243 { "msg", builtin_msg, mhtype_num, mhtype_none }, 1286 { "msg", builtin_msg, mhtype_num, mhtype_none },
1244 { "cur", builtin_cur, mhtype_num, mhtype_none }, 1287 { "cur", builtin_cur, mhtype_num, mhtype_none },
1245 { "size", builtin_size, mhtype_num, mhtype_none }, 1288 { "size", builtin_size, mhtype_num, mhtype_none },
...@@ -1258,7 +1301,7 @@ mh_builtin_t builtin_tab[] = { ...@@ -1258,7 +1301,7 @@ mh_builtin_t builtin_tab[] = {
1258 { "divide", builtin_divide, mhtype_num, mhtype_num }, 1301 { "divide", builtin_divide, mhtype_num, mhtype_num },
1259 { "modulo", builtin_modulo, mhtype_num, mhtype_num }, 1302 { "modulo", builtin_modulo, mhtype_num, mhtype_num },
1260 { "num", builtin_num, mhtype_num, mhtype_num }, 1303 { "num", builtin_num, mhtype_num, mhtype_num },
1261 { "lit", builtin_lit, mhtype_str, mhtype_str }, 1304 { "lit", builtin_lit, mhtype_str, mhtype_str, 1 },
1262 { "getenv", builtin_getenv, mhtype_str, mhtype_str }, 1305 { "getenv", builtin_getenv, mhtype_str, mhtype_str },
1263 { "profile", builtin_profile, mhtype_str, mhtype_str }, 1306 { "profile", builtin_profile, mhtype_str, mhtype_str },
1264 { "nonzero", builtin_nonzero, mhtype_num, mhtype_num, 1 }, 1307 { "nonzero", builtin_nonzero, mhtype_num, mhtype_num, 1 },
......