10 date 95.12.06.20.59.41; author jromine; state Exp;
15 date 93.08.20.15.48.14; author jromine; state Exp;
20 date 93.06.12.06.46.16; author jromine; state Exp;
25 date 93.02.26.21.56.37; author jromine; state Exp;
30 date 92.12.15.00.20.22; author jromine; state Exp;
35 date 92.11.24.18.06.01; author jromine; state Exp;
40 date 92.11.09.17.53.13; author jromine; state Exp;
45 date 92.11.05.17.02.34; author jromine; state Exp;
50 date 92.10.26.22.49.45; author jromine; state Exp;
55 date 92.02.09.07.11.55; author jromine; state Exp;
60 date 92.01.31.21.49.21; author jromine; state Exp;
65 date 92.01.24.18.09.25; author jromine; state Exp;
70 date 92.01.23.23.10.58; author jromine; state Exp;
75 date 91.01.09.22.34.45; author mh; state Exp;
80 date 90.12.27.17.19.03; author mh; state Exp;
85 date 90.04.05.15.30.45; author sources; state Exp;
90 date 90.04.05.14.44.48; author sources; state Exp;
95 date 90.03.23.15.16.29; author sources; state Exp;
100 date 90.03.23.14.38.52; author sources; state Exp;
105 date 90.03.13.15.41.41; author sources; state Exp;
110 date 90.02.21.16.03.22; author sources; state Exp;
115 date 90.02.21.15.58.58; author sources; state Exp;
120 date 90.02.06.16.34.54; author sources; state Exp;
125 date 90.02.06.13.02.35; author sources; state Exp;
130 date 90.01.30.10.44.13; author sources; state Exp;
141 @x.400 fixes from mtr
144 @/* formatsbr.c - format string interpretation */
146 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.24 1993/08/20 15:48:14 jromine Exp jromine $";
150 #include "../h/addrsbr.h"
151 #include "../h/formatsbr.h"
152 #include "../zotnet/tws.h"
153 #include "../h/fmtcompile.h"
156 #include <sys/types.h>
157 #include <sys/stat.h>
162 #define NFMTS MAXARGS
165 static char *formats = 0;
166 extern char *formataddr (); /* hook for custom address formatting */
168 struct msgs *fmt_current_folder; /* current folder (set by main program) */
172 static int get_x400_comp();
174 extern int fmt_norm; /* defined in sbr/formatdef.c = AD_NAME */
175 struct mailname fmt_mnull;
182 /* MAJOR HACK: See MHCHANGES for discussion */
184 char *new_fs (form, format, def)
196 if ((fp = fopen (libpath (form), "r")) == NULL)
197 adios (form, "unable to open format file");
199 if (fstat (fileno (fp), &st) == NOTOK)
200 adios (form, "unable to stat format file");
202 if ((formats = malloc ((unsigned) st.st_size + 1)) == NULLCP)
203 adios (form, "unable to allocate space for format");
205 if (read (fileno(fp), formats, (int) st.st_size) != st.st_size)
206 adios (form, "error reading format file");
208 formats[st.st_size] = '\0';
213 formats = getcpy (format ? format : def);
223 static normalize (cp)
228 for (dp = cp; *cp; cp++)
233 #define grot(y,z) case y: *dp++ = z; break;
255 * test if string "sub" appears anywhere in string "str"
256 * (case insensitive).
259 static int match (str, sub)
270 c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
271 while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
275 s1 = sub + 1; s2 = str;
276 while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2))
283 while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
287 s1 = sub + 1; s2 = str;
288 while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
298 /* macros to format data */
300 #define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\
301 if((i = (num))<0) i = -(num);\
302 if((c = (wid))<0) c = -c;\
305 *--sp = (i % 10) + '0';\
307 } while (i > 0 && sp > cp);\
310 else if ((num) < 0 && sp > cp)\
316 #define PUTD(cp, num) if (cp < ep){\
317 if((i = (num))==0) *cp++ = '0';\
320 *cp++ = '-', i = -(num);\
324 while (cp < ep && c > 1) {\
326 *cp++ = (i / c) + '0';\
332 #define PUTSF(cp, str, wid, fill) {\
334 if ((i = (wid)) < 0) {\
344 while( --i >= c && cp < ep)\
349 while ((c = *sp) && (iscntrl(c) || isspace(c)))\
352 while ((c = *sp++) && --i >= 0 && cp < ep)\
356 while ((c = *sp) && (iscntrl(c) || isspace(c)))\
362 while( --i >= 0 && cp < ep)\
365 #define PUTS(cp, str) {\
367 while ((c = *sp) && (iscntrl(c) || isspace(c)))\
369 while((c = *sp++) && cp < ep)\
373 while ((c = *sp) && (iscntrl(c) || isspace(c)))\
380 #define PUTSF(cp, str, wid, fill) {\
382 if ((i = (wid)) < 0) {\
392 while( --i >= c && cp < ep)\
397 while ((c = *sp) && c <= 32)\
400 while ((c = *sp++) && --i >= 0 && cp < ep)\
404 while ((c = *sp) && c <= 32)\
410 while( --i >= 0 && cp < ep)\
413 #define PUTS(cp, str) {\
415 while ((c = *sp) && c <= 32)\
417 while( (c = *sp++) && cp < ep)\
421 while ( (c = *sp) && c <= 32 )\
430 static char *lmonth[] = { "January", "February","March", "April",
431 "May", "June", "July", "August",
432 "September","October", "November","December" };
434 static char *get_x400_friendly (mbox, buffer)
448 if (get_x400_comp (mbox, "/PN=", buffer)) {
449 for (mbox = buffer; mbox = index (mbox, '.'); )
455 if (!get_x400_comp (mbox, "/S=", surname))
458 if (get_x400_comp (mbox, "/G=", given))
459 (void) sprintf (buffer, "%s %s", given, surname);
461 (void) strcpy (buffer, surname);
466 static int get_x400_comp (mbox, key, buffer)
474 if ((idx = stringdex (key, mbox)) < 0
475 || !(cp = index (mbox += idx + strlen (key), '/')))
478 (void) sprintf (buffer, "%*.*s", cp - mbox, cp - mbox, mbox);
483 fmtscan (format, scanl, width, dat)
484 struct format *format;
489 register char *cp = scanl;
490 register char *ep = scanl + width - 1;
491 register struct format *fmt = format;
492 register char *str = NULLCP;
493 register int value = 0;
497 register struct comp *comp;
498 register struct tws *tws;
499 register struct mailname *mn;
506 switch (fmt->f_type) {
509 PUTS (cp, fmt->f_comp->c_text);
512 PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill);
517 while( (c = *sp++) && cp < ep)
526 ljust++; /* XXX should do something with this */
528 while( (c = *sp++) && --i >= 0 && cp < ep)
530 while( --i >= 0 && cp < ep)
538 PUTSF (cp, str, fmt->f_width, fmt->f_fill);
541 adios (NULLCP, "internal error (FT_STRFW)");
547 PUTDF (cp, value, fmt->f_width, fmt->f_fill);
558 if (!(value = (str && *str))) {
565 if (!(value = (str == NULLCP || *str == 0))) {
572 if (value != fmt->f_value) {
579 if (value == fmt->f_value) {
586 if (value <= fmt->f_value) {
593 if (!(value = (str && match (str, fmt->f_text)))) {
601 value = match (str, fmt->f_text);
607 if (!(value = (str && uprf (str, fmt->f_text)))) {
614 value = uprf (str, fmt->f_text);
618 value = (str != NULLCP && *str != 0);
622 value = (str == NULLCP || *str == 0);
626 value = (fmt->f_value == value);
630 value = (fmt->f_value != value);
634 value = (fmt->f_value > value);
645 str = fmt->f_comp->c_text;
651 if (!(str = getenv (fmt->f_text)))
655 if (!(str = m_find (fmt->f_text)))
662 (void) strcpy(buffer, str);
664 while (isspace(*str))
667 if ((i = fmt->f_width) < 0) {
672 if (!ljust && i > 0 && strlen(str) > i)
675 xp += strlen(str) - 1;
676 while (xp > str && isspace(*xp))
678 if (ljust && i > 0 && strlen(str) > i)
679 str += strlen(str) - i;
684 value = fmt->f_comp->c_flags;
687 value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
690 value = fmt->f_value;
693 value = dat[fmt->f_value];
698 case FT_LV_CHAR_LEFT:
699 value = width - (cp - scanl);
702 value += fmt->f_value;
705 value = fmt->f_value - value;
709 value = value / fmt->f_value;
715 value = value % fmt->f_value;
724 value = fmt->f_comp->c_tws->tw_sec;
727 value = fmt->f_comp->c_tws->tw_min;
730 value = fmt->f_comp->c_tws->tw_hour;
733 value = fmt->f_comp->c_tws->tw_mday;
736 value = fmt->f_comp->c_tws->tw_mon + 1;
739 str = tw_moty[fmt->f_comp->c_tws->tw_mon];
742 str = lmonth[fmt->f_comp->c_tws->tw_mon];
745 str = dtwszone (fmt->f_comp->c_tws);
749 value = fmt->f_comp->c_tws->tw_year;
751 value = (fmt->f_comp->c_tws->tw_year) % 100;
755 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
757 value = tws->tw_wday;
760 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
762 str = tw_dotw[tws->tw_wday];
765 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
767 str = tw_ldotw[tws->tw_wday];
770 value = fmt->f_comp->c_tws->tw_yday;
773 value = fmt->f_comp->c_tws->tw_zone;
776 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
777 value = twclock(fmt->f_comp->c_tws);
780 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
781 value = twclock(fmt->f_comp->c_tws);
782 value = time((long *) 0) - value;
785 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
787 switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
796 if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP)
802 value = fmt->f_comp->c_tws->tw_flags & TW_DST;
805 str = dasctime ( fmt->f_comp->c_tws , TW_ZONE);
808 str = dasctime ( fmt->f_comp->c_tws, TW_NULL);
812 str = fmt->f_comp->c_mn->m_pers;
815 str = fmt->f_comp->c_mn->m_mbox;
818 str = fmt->f_comp->c_mn->m_host;
821 str = fmt->f_comp->c_mn->m_path;
824 str = fmt->f_comp->c_mn->m_gname;
827 str = fmt->f_comp->c_mn->m_note;
830 str = adrformat( fmt->f_comp->c_mn );
833 value = fmt->f_comp->c_mn->m_type;
836 value = fmt->f_comp->c_mn->m_ingrp;
839 value = fmt->f_comp->c_mn->m_nohost;
844 str = fmt->f_comp->c_mn->m_mbox;
846 if ((mn = fmt -> f_comp -> c_mn) == &fmt_mnull) {
847 str = fmt -> f_comp -> c_text;
850 if (fmt -> f_type == FT_LS_ADDR)
852 if (!(str = mn -> m_pers)
853 && (!(str = get_x400_friendly (mn -> m_mbox, buffer)))) {
854 if (str = mn -> m_note) {
855 (void) strcpy (buffer, str);
859 sp = str + strlen (str) - 1;
873 switch (mn -> m_type) {
878 (void) sprintf (str = buffer, "%s!%s",
879 mn -> m_host, mn -> m_mbox);
883 (void) sprintf (str= buffer, "%s@@%s", mn -> m_mbox,
895 if ((l = comp->c_tws->tw_clock) == 0)
896 l = twclock(comp->c_tws);
897 tws = dlocaltime(&l);
903 if ((l = comp->c_tws->tw_clock) == 0)
904 l = twclock(comp->c_tws);
911 if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
914 } else if (comp->c_flags >= 0) {
915 bzero ((char *) comp -> c_tws, sizeof *comp -> c_tws);
921 /* hook for custom address list formatting (see replsbr.c) */
922 str = formataddr (savestr, str);
926 /* output the str register as an address component,
927 * splitting it into multiple lines if necessary. The
928 * value reg. contains the max line length. The lit.
929 * field may contain a string to prepend to the result
933 register char *lp = str;
935 register int wid = value;
936 register int len = strlen (str);
937 register char *lastb;
940 indent = strlen (sp);
942 while( (c = *sp++) && cp < ep)
945 /* try to break at a comma; failing that, break at a
946 * space, failing that, just split the line.
948 lastb = 0; sp = lp + wid;
949 while (sp > lp && (c = *--sp) != ',') {
950 if (! lastb && isspace(c))
957 while (cp < ep && lp <= sp)
960 for (i=indent; cp < ep && i > 0; i--)
971 if (comp->c_mn != &fmt_mnull)
973 if ((sp = comp->c_text) && (sp = getname(sp)) &&
974 (mn = getm (sp, NULLCP, 0, fmt_norm, NULLCP))) {
979 while (getname("")) /* XXX */
981 comp->c_mn = &fmt_mnull;
987 * if there's no component, we say true. Otherwise we
988 * say "true" only if we can parse the address and it
989 * matches one of our addresses.
992 if (comp->c_mn != &fmt_mnull)
994 if ((sp = comp->c_text) && (sp = getname(sp)) &&
995 (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) {
997 comp->c_flags = ismymbox(mn);
998 while (sp = getname(sp))
999 if (comp->c_flags == 0 &&
1000 (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP)))
1001 comp->c_flags |= ismymbox(mn);
1003 while (getname("")) /* XXX */
1005 comp->c_flags = (comp->c_text == 0);
1006 comp->c_mn = &fmt_mnull;
1012 /* If we're working on a folder (as opposed to a file), add the
1013 * current msg to sequence given in literal field. Don't
1014 * disturb string or value registers.
1016 if (fmt_current_folder)
1017 (void)m_seqadd(fmt_current_folder, fmt->f_text, dat[0], -1);
1028 return ((struct format *)0);
1032 while (fmt->f_type != FT_DONE)
1037 return (fmt -> f_value ? ++fmt : (struct format *)0);
1046 @small patch to make funny X.400 addresses look better /mtr
1051 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.23 1993/06/12 06:46:16 jromine Exp jromine $";
1054 if ((str = mn -> m_pers) == NULL)
1055 if ((str = mn -> m_note)) {
1056 (void) strcpy (buffer, str);
1060 sp = str + strlen(str) - 1;
1069 } else if (!(str = get_x400_friendly (mn -> m_mbox, buffer))) {
1071 switch (mn -> m_type) {
1077 (void) sprintf (buffer, "%s!%s",
1083 (void) sprintf (buffer, "%s@@%s",
1084 mn -> m_mbox, mn -> m_host);
1095 @add %(profile xxx) to return m_find(xxx)
1100 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.22 1993/02/26 21:56:37 jromine Exp jromine $";
1114 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.21 1992/12/15 00:20:22 jromine Exp jromine $";
1126 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.20 1992/11/24 18:06:01 jromine Exp jromine $";
1129 if (read (fileno(fp), formats, st.st_size) != st.st_size)
1140 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.19 1992/11/09 17:53:13 jromine Exp jromine $";
1153 @add YEARMOD to force 2-digit years
1158 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.18 1992/11/05 17:02:34 jromine Exp jromine $";
1165 @try to be friendly with x400 rfc987 addresses
1170 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.17 1992/10/26 22:49:45 jromine Exp jromine $";
1183 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.16 1992/02/09 07:11:55 jromine Exp jromine $";
1194 @put Van Jacobson "addtoseq" option under "options LBL"
1195 make sure combined "if"s set value (for later testing)
1201 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.15 1992/01/31 21:49:21 jromine Exp $";
1218 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.14 1992/01/24 18:09:25 jromine Exp jromine $";
1224 if (str == NULLCP || *str == 0) {
1227 if (str != NULLCP && *str != 0) {
1230 if (!str || !match (str, fmt->f_text)) {
1233 value = match (str, fmt->f_text);
1236 if (!str || !uprf (str, fmt->f_text)) {
1249 @move fmt_norm to formatdef.c for shared libs
1254 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.13 1992/01/23 23:10:58 jromine Exp jromine $";
1263 if (str == NULLCP || *str == NULL) {
1266 if (str != NULLCP && *str != NULL) {
1269 value = (str != NULLCP && *str != NULL);
1272 value = (str == NULLCP || *str == NULL);
1281 @new formatsbr changes under JLR
1286 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.12 1991/01/09 22:34:45 mh Exp jromine $";
1289 int fmt_norm = AD_NAME;
1295 @allow %-n(trim) to right-justify and length limit
1301 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.11 90/12/27 17:19:03 mh Exp Locker: mh $";
1313 @add "addr" address format.
1319 static char ident[] = "@@(#)$Id: formatsbr.c,v 1.10 90/04/05 15:30:45 sources Exp Locker: mh $";
1322 ljust++; /* XXX should do something with this */
1325 if (i > 0 && strlen(str) > i)
1337 static char ident[] = "@@(#)$Id:$";
1343 switch (mn -> m_type) {
1355 static char ident[] = "$Id:";
1361 @remove JLR ifdef around fix
1370 @make friendly just return text if unparseable
1386 @horrible fix for bad address parsing
1391 mn = fmt -> f_comp -> c_mn;
1397 @Fixes from Van Jacobson
1418 fmtscan(format, scanl, width, dat)
1421 str = dasctime(fmt->f_comp->c_tws, TW_ZONE);
1424 str = dasctime(fmt->f_comp->c_tws, TW_NULL);
1432 @make "friendly" more friendly -- it'll pick up "(full name)" now.
1450 while( (c = *sp++) && --i >= 0 && cp < ep)\
1454 while ( (c = *sp) && c <= 32 )\
1459 fmtscan (format, scanl, width, dat)
1466 sp = fmt->f_text; i = fmt->f_width;
1469 if (! match (str, fmt->f_text)) {
1474 if (! uprf (str, fmt->f_text)) {
1484 str = dasctime ( fmt->f_comp->c_tws , TW_ZONE);
1487 str = dasctime ( fmt->f_comp->c_tws, TW_NULL);
1514 #define grot(x) case 'x': *dp++ = '\x'; break;