65 |
|
|
66 |
#define strobj_ptr(p) ((p)->ptr ? (p)->ptr : "") |
#define strobj_ptr(p) ((p)->ptr ? (p)->ptr : "") |
67 |
#define strobj_len(p) strlen((p)->ptr) |
#define strobj_len(p) strlen((p)->ptr) |
68 |
|
#define strobj_is_null(p) ((p)->ptr == NULL) |
69 |
#define strobj_is_static(p) ((p)->size == 0) |
#define strobj_is_static(p) ((p)->size == 0) |
70 |
|
|
71 |
static void |
static void |
103 |
static void |
static void |
104 |
strobj_copy (strobj_t *lvalue, strobj_t *rvalue) |
strobj_copy (strobj_t *lvalue, strobj_t *rvalue) |
105 |
{ |
{ |
106 |
if (lvalue->size >= strobj_len (rvalue) + 1) |
if (strobj_is_null (rvalue)) |
107 |
|
strobj_free (lvalue); |
108 |
|
else if (lvalue->size >= strobj_len (rvalue) + 1) |
109 |
memcpy (lvalue->ptr, strobj_ptr (rvalue), strobj_len (rvalue) + 1); |
memcpy (lvalue->ptr, strobj_ptr (rvalue), strobj_len (rvalue) + 1); |
110 |
else |
else |
111 |
{ |
{ |
115 |
} |
} |
116 |
} |
} |
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 |
|
|
137 |
/* Compress whitespace in a string */ |
/* Compress whitespace in a string */ |
138 |
static void |
static void |
139 |
compress_ws (char *str, size_t *size) |
compress_ws (char *str, size_t *size) |
163 |
|
|
164 |
/* Print len bytes from str into mach->outbuf */ |
/* Print len bytes from str into mach->outbuf */ |
165 |
static void |
static void |
166 |
print_string (struct mh_machine *mach, char *str, size_t len) |
print_string (struct mh_machine *mach, size_t width, char *str, size_t len) |
167 |
{ |
{ |
168 |
size_t rest = strlen (str); |
size_t rest = strlen (str); |
169 |
|
|
170 |
if (len > rest) |
if (len > rest) |
171 |
len = rest; |
len = rest; |
172 |
|
if (!width) |
173 |
|
width = mach->width; |
174 |
rest = mach->width - mach->ind; |
rest = mach->width - mach->ind; |
175 |
if (len > rest) |
if (len > rest) |
176 |
len = rest; |
len = rest; |
179 |
} |
} |
180 |
|
|
181 |
static void |
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 |
189 |
reset_fmt_defaults (struct mh_machine *mach) |
reset_fmt_defaults (struct mh_machine *mach) |
190 |
{ |
{ |
191 |
mach->fmtflags = 0; |
mach->fmtflags = 0; |
366 |
else |
else |
367 |
ptr = buf; |
ptr = buf; |
368 |
|
|
369 |
print_string (&mach, ptr, strlen (ptr)); |
print_string (&mach, 0, ptr, strlen (ptr)); |
370 |
reset_fmt_defaults (&mach); |
reset_fmt_defaults (&mach); |
371 |
} |
} |
372 |
break; |
break; |
388 |
mach.outbuf[mach.ind] = padchar; |
mach.outbuf[mach.ind] = padchar; |
389 |
} |
} |
390 |
|
|
391 |
print_string (&mach, strobj_ptr (&mach.reg_str), fmtwidth); |
print_string (&mach, 0, strobj_ptr (&mach.reg_str), fmtwidth); |
392 |
reset_fmt_defaults (&mach); |
reset_fmt_defaults (&mach); |
393 |
} |
} |
394 |
else if (mach.reg_str.ptr) |
else |
395 |
{ |
print_obj (&mach, 0, &mach.reg_str); |
|
print_string (&mach, |
|
|
strobj_ptr (&mach.reg_str), |
|
|
strobj_len (&mach.reg_str)); |
|
|
} |
|
396 |
break; |
break; |
397 |
|
|
398 |
case mhop_fmtspec: |
case mhop_fmtspec: |
399 |
mach.fmtflags = MHI_NUM(mach.prog[mach.pc++]); |
mach.fmtflags = MHI_NUM(mach.prog[mach.pc++]); |
400 |
break; |
break; |
401 |
|
|
402 |
default: |
default: |
403 |
mh_error ("Unknown opcode: %x", opcode); |
mh_error ("Unknown opcode: %x", opcode); |
404 |
abort (); |
abort (); |
564 |
static void |
static void |
565 |
builtin_lit (struct mh_machine *mach) |
builtin_lit (struct mh_machine *mach) |
566 |
{ |
{ |
567 |
strobj_assign (&mach->reg_str, &mach->arg_str); |
/* do nothing */ |
568 |
} |
} |
569 |
|
|
570 |
static void |
static void |
675 |
char *date = strobj_ptr (&mach->arg_str); |
char *date = strobj_ptr (&mach->arg_str); |
676 |
const char *p = date; |
const char *p = date; |
677 |
|
|
678 |
if (parse822_date_time(&p, date+strlen(date), tm, tz)) |
if (parse822_date_time (&p, date+strlen(date), tm, tz)) |
679 |
{ |
{ |
680 |
mh_error ("can't parse date: [%s]", date); |
mh_error ("can't parse date: [%s]", date); |
681 |
return -1; |
return -1; |
1228 |
builtin_formataddr (struct mh_machine *mach) |
builtin_formataddr (struct mh_machine *mach) |
1229 |
{ |
{ |
1230 |
address_t addr; |
address_t addr; |
1231 |
size_t num = 0, n, i; |
size_t num = 0, n, i, length = 0, reglen; |
1232 |
char buf[80], *p; |
char buf[80], *p; |
1233 |
|
|
1234 |
if (address_create (&addr, strobj_ptr (&mach->arg_str))) |
if (address_create (&addr, strobj_ptr (&mach->arg_str))) |
1236 |
address_get_count (addr, &num); |
address_get_count (addr, &num); |
1237 |
for (i = 1; i <= num; i++) |
for (i = 1; i <= num; i++) |
1238 |
{ |
{ |
1239 |
|
if (address_get_personal (addr, i, buf, sizeof buf, &n) == 0 |
1240 |
|
&& n != 0) |
1241 |
|
length += n+1; /* + space */ |
1242 |
address_get_email (addr, i, buf, sizeof buf, &n); |
address_get_email (addr, i, buf, sizeof buf, &n); |
1243 |
num += n+1; |
length += n+3; /* two brackets + (eventual) comma */ |
1244 |
} |
} |
1245 |
|
|
1246 |
num += strobj_len (&mach->reg_str) + 1; |
if (strobj_is_null (&mach->reg_str)) |
1247 |
mach->reg_str.ptr = xrealloc (mach->reg_str.ptr, num); |
reglen = 0; |
1248 |
mach->reg_str.size = num + 1; |
else |
1249 |
p = strobj_ptr (&mach->reg_str) + strobj_len (&mach->reg_str) ; |
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; |
1253 |
for (i = 1; i <= num; i++) |
for (i = 1; i <= num; i++) |
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 |
|
} |
1263 |
address_get_email (addr, i, buf, sizeof buf, &n); |
address_get_email (addr, i, buf, sizeof buf, &n); |
1264 |
|
*p++ = '<'; |
1265 |
memcpy (p, buf, n); |
memcpy (p, buf, n); |
1266 |
p += n; |
p += n; |
1267 |
|
*p++ = '>'; |
1268 |
} |
} |
1269 |
*p = 0; |
*p = 0; |
1270 |
} |
} |
1271 |
|
|
1272 |
/* putaddr literal print str address list with |
/* putaddr literal print str address list with |
1273 |
arg as optional label; |
arg as optional label; |
1274 |
get line width from num */ |
get line width from num */ |
1275 |
static void |
static void |
1276 |
builtin_putaddr (struct mh_machine *mach) |
builtin_putaddr (struct mh_machine *mach) |
1277 |
{ |
{ |
1278 |
/*FIXME:*/ |
print_obj (mach, mach->reg_num, &mach->arg_str); |
1279 |
builtin_not_implemented ("putaddr"); |
print_obj (mach, mach->reg_num, &mach->reg_str); |
1280 |
} |
} |
1281 |
|
|
1282 |
/* Builtin function table */ |
/* Builtin function table */ |
1283 |
|
|
1284 |
mh_builtin_t builtin_tab[] = { |
mh_builtin_t builtin_tab[] = { |
1285 |
/* Name Handling function Return type Arg type */ |
/* Name Handling function Return type Arg type Opt. arg */ |
1286 |
{ "msg", builtin_msg, mhtype_num, mhtype_none }, |
{ "msg", builtin_msg, mhtype_num, mhtype_none }, |
1287 |
{ "cur", builtin_cur, mhtype_num, mhtype_none }, |
{ "cur", builtin_cur, mhtype_num, mhtype_none }, |
1288 |
{ "size", builtin_size, mhtype_num, mhtype_none }, |
{ "size", builtin_size, mhtype_num, mhtype_none }, |
1301 |
{ "divide", builtin_divide, mhtype_num, mhtype_num }, |
{ "divide", builtin_divide, mhtype_num, mhtype_num }, |
1302 |
{ "modulo", builtin_modulo, mhtype_num, mhtype_num }, |
{ "modulo", builtin_modulo, mhtype_num, mhtype_num }, |
1303 |
{ "num", builtin_num, mhtype_num, mhtype_num }, |
{ "num", builtin_num, mhtype_num, mhtype_num }, |
1304 |
{ "lit", builtin_lit, mhtype_str, mhtype_str }, |
{ "lit", builtin_lit, mhtype_str, mhtype_str, 1 }, |
1305 |
{ "getenv", builtin_getenv, mhtype_str, mhtype_str }, |
{ "getenv", builtin_getenv, mhtype_str, mhtype_str }, |
1306 |
{ "profile", builtin_profile, mhtype_str, mhtype_str }, |
{ "profile", builtin_profile, mhtype_str, mhtype_str }, |
1307 |
{ "nonzero", builtin_nonzero, mhtype_num, mhtype_num, 1 }, |
{ "nonzero", builtin_nonzero, mhtype_num, mhtype_num, 1 }, |