1c2aa98e2SPeter Wemm /* 2602a2b1bSGregory Neil Shapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 1406f25ae9SGregory Neil Shapiro #include <sendmail.h> 15c2aa98e2SPeter Wemm 1640266059SGregory Neil Shapiro SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro Exp $") 1740266059SGregory Neil Shapiro 18193538b7SGregory Neil Shapiro #if MAXMACROID != (BITMAPBITS - 1) 19193538b7SGregory Neil Shapiro ERROR Read the comment in conf.h 20193538b7SGregory Neil Shapiro #endif /* MAXMACROID != (BITMAPBITS - 1) */ 21c2aa98e2SPeter Wemm 2240266059SGregory Neil Shapiro static char *MacroName[MAXMACROID + 1]; /* macro id to name table */ 23193538b7SGregory Neil Shapiro int NextMacroId = 0240; /* codes for long named macros */ 24c2aa98e2SPeter Wemm 25c2aa98e2SPeter Wemm /* 2640266059SGregory Neil Shapiro ** INITMACROS -- initialize the macro system 2740266059SGregory Neil Shapiro ** 2840266059SGregory Neil Shapiro ** This just involves defining some macros that are actually 2940266059SGregory Neil Shapiro ** used internally as metasymbols to be themselves. 3040266059SGregory Neil Shapiro ** 3140266059SGregory Neil Shapiro ** Parameters: 3240266059SGregory Neil Shapiro ** none. 3340266059SGregory Neil Shapiro ** 3440266059SGregory Neil Shapiro ** Returns: 3540266059SGregory Neil Shapiro ** none. 3640266059SGregory Neil Shapiro ** 3740266059SGregory Neil Shapiro ** Side Effects: 3840266059SGregory Neil Shapiro ** initializes several macros to be themselves. 3940266059SGregory Neil Shapiro */ 4040266059SGregory Neil Shapiro 4140266059SGregory Neil Shapiro struct metamac MetaMacros[] = 4240266059SGregory Neil Shapiro { 4340266059SGregory Neil Shapiro /* LHS pattern matching characters */ 4440266059SGregory Neil Shapiro { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE }, 4540266059SGregory Neil Shapiro { '=', MATCHCLASS }, { '~', MATCHNCLASS }, 4640266059SGregory Neil Shapiro 4740266059SGregory Neil Shapiro /* these are RHS metasymbols */ 4840266059SGregory Neil Shapiro { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER }, 4940266059SGregory Neil Shapiro { '>', CALLSUBR }, 5040266059SGregory Neil Shapiro 5140266059SGregory Neil Shapiro /* the conditional operations */ 5240266059SGregory Neil Shapiro { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI }, 5340266059SGregory Neil Shapiro 5440266059SGregory Neil Shapiro /* the hostname lookup characters */ 5540266059SGregory Neil Shapiro { '[', HOSTBEGIN }, { ']', HOSTEND }, 5640266059SGregory Neil Shapiro { '(', LOOKUPBEGIN }, { ')', LOOKUPEND }, 5740266059SGregory Neil Shapiro 5840266059SGregory Neil Shapiro /* miscellaneous control characters */ 5940266059SGregory Neil Shapiro { '&', MACRODEXPAND }, 6040266059SGregory Neil Shapiro 6140266059SGregory Neil Shapiro { '\0', '\0' } 6240266059SGregory Neil Shapiro }; 6340266059SGregory Neil Shapiro 6440266059SGregory Neil Shapiro #define MACBINDING(name, mid) \ 6540266059SGregory Neil Shapiro stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \ 6640266059SGregory Neil Shapiro MacroName[mid] = name; 6740266059SGregory Neil Shapiro 6840266059SGregory Neil Shapiro void 6940266059SGregory Neil Shapiro initmacros(e) 7040266059SGregory Neil Shapiro register ENVELOPE *e; 7140266059SGregory Neil Shapiro { 7240266059SGregory Neil Shapiro register struct metamac *m; 7340266059SGregory Neil Shapiro register int c; 7440266059SGregory Neil Shapiro char buf[5]; 7540266059SGregory Neil Shapiro 7640266059SGregory Neil Shapiro for (m = MetaMacros; m->metaname != '\0'; m++) 7740266059SGregory Neil Shapiro { 7840266059SGregory Neil Shapiro buf[0] = m->metaval; 7940266059SGregory Neil Shapiro buf[1] = '\0'; 8040266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, m->metaname, buf); 8140266059SGregory Neil Shapiro } 8240266059SGregory Neil Shapiro buf[0] = MATCHREPL; 8340266059SGregory Neil Shapiro buf[2] = '\0'; 8440266059SGregory Neil Shapiro for (c = '0'; c <= '9'; c++) 8540266059SGregory Neil Shapiro { 8640266059SGregory Neil Shapiro buf[1] = c; 8740266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, c, buf); 8840266059SGregory Neil Shapiro } 8940266059SGregory Neil Shapiro 9040266059SGregory Neil Shapiro /* set defaults for some macros sendmail will use later */ 9140266059SGregory Neil Shapiro macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON"); 9240266059SGregory Neil Shapiro 9340266059SGregory Neil Shapiro /* set up external names for some internal macros */ 9440266059SGregory Neil Shapiro MACBINDING("opMode", MID_OPMODE); 9540266059SGregory Neil Shapiro /*XXX should probably add equivalents for all short macros here XXX*/ 9640266059SGregory Neil Shapiro } 9740266059SGregory Neil Shapiro /* 98c2aa98e2SPeter Wemm ** EXPAND -- macro expand a string using $x escapes. 99c2aa98e2SPeter Wemm ** 100c2aa98e2SPeter Wemm ** Parameters: 101c2aa98e2SPeter Wemm ** s -- the string to expand. 102c2aa98e2SPeter Wemm ** buf -- the place to put the expansion. 103c2aa98e2SPeter Wemm ** bufsize -- the size of the buffer. 104c2aa98e2SPeter Wemm ** e -- envelope in which to work. 105c2aa98e2SPeter Wemm ** 106c2aa98e2SPeter Wemm ** Returns: 107c2aa98e2SPeter Wemm ** none. 108c2aa98e2SPeter Wemm ** 109c2aa98e2SPeter Wemm ** Side Effects: 110c2aa98e2SPeter Wemm ** none. 111c2aa98e2SPeter Wemm */ 112c2aa98e2SPeter Wemm 113c2aa98e2SPeter Wemm void 114c2aa98e2SPeter Wemm expand(s, buf, bufsize, e) 115c2aa98e2SPeter Wemm register char *s; 116c2aa98e2SPeter Wemm register char *buf; 117c2aa98e2SPeter Wemm size_t bufsize; 118c2aa98e2SPeter Wemm register ENVELOPE *e; 119c2aa98e2SPeter Wemm { 120c2aa98e2SPeter Wemm register char *xp; 121c2aa98e2SPeter Wemm register char *q; 122c2aa98e2SPeter Wemm bool skipping; /* set if conditionally skipping output */ 12340266059SGregory Neil Shapiro bool recurse; /* set if recursion required */ 12440266059SGregory Neil Shapiro size_t i; 125c2aa98e2SPeter Wemm int skiplev; /* skipping nesting level */ 126c2aa98e2SPeter Wemm int iflev; /* if nesting level */ 127c2aa98e2SPeter Wemm char xbuf[MACBUFSIZE]; 128c2aa98e2SPeter Wemm static int explevel = 0; 129c2aa98e2SPeter Wemm 130c2aa98e2SPeter Wemm if (tTd(35, 24)) 131c2aa98e2SPeter Wemm { 13240266059SGregory Neil Shapiro sm_dprintf("expand("); 133c2aa98e2SPeter Wemm xputs(s); 13440266059SGregory Neil Shapiro sm_dprintf(")\n"); 135c2aa98e2SPeter Wemm } 136c2aa98e2SPeter Wemm 13740266059SGregory Neil Shapiro recurse = false; 13840266059SGregory Neil Shapiro skipping = false; 139c2aa98e2SPeter Wemm skiplev = 0; 140c2aa98e2SPeter Wemm iflev = 0; 141c2aa98e2SPeter Wemm if (s == NULL) 142c2aa98e2SPeter Wemm s = ""; 143c2aa98e2SPeter Wemm for (xp = xbuf; *s != '\0'; s++) 144c2aa98e2SPeter Wemm { 145c2aa98e2SPeter Wemm int c; 146c2aa98e2SPeter Wemm 147c2aa98e2SPeter Wemm /* 148c2aa98e2SPeter Wemm ** Check for non-ordinary (special?) character. 149c2aa98e2SPeter Wemm ** 'q' will be the interpolated quantity. 150c2aa98e2SPeter Wemm */ 151c2aa98e2SPeter Wemm 152c2aa98e2SPeter Wemm q = NULL; 153c2aa98e2SPeter Wemm c = *s; 154c2aa98e2SPeter Wemm switch (c & 0377) 155c2aa98e2SPeter Wemm { 156c2aa98e2SPeter Wemm case CONDIF: /* see if var set */ 157c2aa98e2SPeter Wemm iflev++; 158c2aa98e2SPeter Wemm c = *++s; 159c2aa98e2SPeter Wemm if (skipping) 160c2aa98e2SPeter Wemm skiplev++; 161c2aa98e2SPeter Wemm else 16206f25ae9SGregory Neil Shapiro { 16306f25ae9SGregory Neil Shapiro char *mv; 16406f25ae9SGregory Neil Shapiro 16506f25ae9SGregory Neil Shapiro mv = macvalue(c, e); 16606f25ae9SGregory Neil Shapiro skipping = (mv == NULL || *mv == '\0'); 16706f25ae9SGregory Neil Shapiro } 168c2aa98e2SPeter Wemm continue; 169c2aa98e2SPeter Wemm 170c2aa98e2SPeter Wemm case CONDELSE: /* change state of skipping */ 171c2aa98e2SPeter Wemm if (iflev == 0) 17240266059SGregory Neil Shapiro break; /* XXX: error */ 173c2aa98e2SPeter Wemm if (skiplev == 0) 174c2aa98e2SPeter Wemm skipping = !skipping; 175c2aa98e2SPeter Wemm continue; 176c2aa98e2SPeter Wemm 177c2aa98e2SPeter Wemm case CONDFI: /* stop skipping */ 178c2aa98e2SPeter Wemm if (iflev == 0) 17940266059SGregory Neil Shapiro break; /* XXX: error */ 180c2aa98e2SPeter Wemm iflev--; 181c2aa98e2SPeter Wemm if (skiplev == 0) 18240266059SGregory Neil Shapiro skipping = false; 183c2aa98e2SPeter Wemm if (skipping) 184c2aa98e2SPeter Wemm skiplev--; 185c2aa98e2SPeter Wemm continue; 186c2aa98e2SPeter Wemm 187c2aa98e2SPeter Wemm case MACROEXPAND: /* macro interpolation */ 188193538b7SGregory Neil Shapiro c = bitidx(*++s); 189c2aa98e2SPeter Wemm if (c != '\0') 190c2aa98e2SPeter Wemm q = macvalue(c, e); 191c2aa98e2SPeter Wemm else 192c2aa98e2SPeter Wemm { 193c2aa98e2SPeter Wemm s--; 194c2aa98e2SPeter Wemm q = NULL; 195c2aa98e2SPeter Wemm } 196c2aa98e2SPeter Wemm if (q == NULL) 197c2aa98e2SPeter Wemm continue; 198c2aa98e2SPeter Wemm break; 199c2aa98e2SPeter Wemm } 200c2aa98e2SPeter Wemm 201c2aa98e2SPeter Wemm /* 202c2aa98e2SPeter Wemm ** Interpolate q or output one character 203c2aa98e2SPeter Wemm */ 204c2aa98e2SPeter Wemm 205c2aa98e2SPeter Wemm if (skipping || xp >= &xbuf[sizeof xbuf - 1]) 206c2aa98e2SPeter Wemm continue; 207c2aa98e2SPeter Wemm if (q == NULL) 208c2aa98e2SPeter Wemm *xp++ = c; 209c2aa98e2SPeter Wemm else 210c2aa98e2SPeter Wemm { 211c2aa98e2SPeter Wemm /* copy to end of q or max space remaining in buf */ 212c2aa98e2SPeter Wemm while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 213c2aa98e2SPeter Wemm { 214c2aa98e2SPeter Wemm /* check for any sendmail metacharacters */ 215c2aa98e2SPeter Wemm if ((c & 0340) == 0200) 21640266059SGregory Neil Shapiro recurse = true; 217c2aa98e2SPeter Wemm *xp++ = c; 218c2aa98e2SPeter Wemm } 219c2aa98e2SPeter Wemm } 220c2aa98e2SPeter Wemm } 221c2aa98e2SPeter Wemm *xp = '\0'; 222c2aa98e2SPeter Wemm 223c2aa98e2SPeter Wemm if (tTd(35, 24)) 224c2aa98e2SPeter Wemm { 22540266059SGregory Neil Shapiro sm_dprintf("expand ==> "); 226c2aa98e2SPeter Wemm xputs(xbuf); 22740266059SGregory Neil Shapiro sm_dprintf("\n"); 228c2aa98e2SPeter Wemm } 229c2aa98e2SPeter Wemm 230c2aa98e2SPeter Wemm /* recurse as appropriate */ 231c2aa98e2SPeter Wemm if (recurse) 232c2aa98e2SPeter Wemm { 233c2aa98e2SPeter Wemm if (explevel < MaxMacroRecursion) 234c2aa98e2SPeter Wemm { 235c2aa98e2SPeter Wemm explevel++; 236c2aa98e2SPeter Wemm expand(xbuf, buf, bufsize, e); 237c2aa98e2SPeter Wemm explevel--; 238c2aa98e2SPeter Wemm return; 239c2aa98e2SPeter Wemm } 240c2aa98e2SPeter Wemm syserr("expand: recursion too deep (%d max)", 241c2aa98e2SPeter Wemm MaxMacroRecursion); 242c2aa98e2SPeter Wemm } 243c2aa98e2SPeter Wemm 244c2aa98e2SPeter Wemm /* copy results out */ 245c2aa98e2SPeter Wemm i = xp - xbuf; 24640266059SGregory Neil Shapiro if (i >= bufsize) 247c2aa98e2SPeter Wemm i = bufsize - 1; 24806f25ae9SGregory Neil Shapiro memmove(buf, xbuf, i); 249c2aa98e2SPeter Wemm buf[i] = '\0'; 250c2aa98e2SPeter Wemm } 25140266059SGregory Neil Shapiro 25240266059SGregory Neil Shapiro /* 25340266059SGregory Neil Shapiro ** MACDEFINE -- bind a macro name to a value 254c2aa98e2SPeter Wemm ** 25540266059SGregory Neil Shapiro ** Set a macro to a value, with fancy storage management. 25640266059SGregory Neil Shapiro ** macdefine will make a copy of the value, if required, 25740266059SGregory Neil Shapiro ** and will ensure that the storage for the previous value 25840266059SGregory Neil Shapiro ** is not leaked. 259c2aa98e2SPeter Wemm ** 260c2aa98e2SPeter Wemm ** Parameters: 26140266059SGregory Neil Shapiro ** mac -- Macro table. 26240266059SGregory Neil Shapiro ** vclass -- storage class of 'value', ignored if value==NULL. 26340266059SGregory Neil Shapiro ** A_HEAP means that the value was allocated by 26440266059SGregory Neil Shapiro ** malloc, and that macdefine owns the storage. 26540266059SGregory Neil Shapiro ** A_TEMP means that value points to temporary storage, 26640266059SGregory Neil Shapiro ** and thus macdefine needs to make a copy. 26740266059SGregory Neil Shapiro ** A_PERM means that value points to storage that 26840266059SGregory Neil Shapiro ** will remain allocated and unchanged for 26940266059SGregory Neil Shapiro ** at least the lifetime of mac. Use A_PERM if: 27040266059SGregory Neil Shapiro ** -- value == NULL, 27140266059SGregory Neil Shapiro ** -- value points to a string literal, 27240266059SGregory Neil Shapiro ** -- value was allocated from mac->mac_rpool 27340266059SGregory Neil Shapiro ** or (in the case of an envelope macro) 27440266059SGregory Neil Shapiro ** from e->e_rpool, 27540266059SGregory Neil Shapiro ** -- in the case of an envelope macro, 27640266059SGregory Neil Shapiro ** value is a string member of the envelope 27740266059SGregory Neil Shapiro ** such as e->e_sender. 27840266059SGregory Neil Shapiro ** id -- Macro id. This is a single character macro name 27940266059SGregory Neil Shapiro ** such as 'g', or a value returned by macid(). 28040266059SGregory Neil Shapiro ** value -- Macro value: either NULL, or a string. 281c2aa98e2SPeter Wemm */ 282c2aa98e2SPeter Wemm 283c2aa98e2SPeter Wemm void 28440266059SGregory Neil Shapiro #if SM_HEAP_CHECK 28540266059SGregory Neil Shapiro macdefine_tagged(mac, vclass, id, value, file, line, grp) 28640266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */ 28740266059SGregory Neil Shapiro macdefine(mac, vclass, id, value) 28840266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 28940266059SGregory Neil Shapiro MACROS_T *mac; 29040266059SGregory Neil Shapiro ARGCLASS_T vclass; 29140266059SGregory Neil Shapiro int id; 29240266059SGregory Neil Shapiro char *value; 29340266059SGregory Neil Shapiro #if SM_HEAP_CHECK 29440266059SGregory Neil Shapiro char *file; 29540266059SGregory Neil Shapiro int line; 29640266059SGregory Neil Shapiro int grp; 29740266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 298c2aa98e2SPeter Wemm { 29940266059SGregory Neil Shapiro char *newvalue; 30006f25ae9SGregory Neil Shapiro 30140266059SGregory Neil Shapiro if (id < 0 || id > MAXMACROID) 30240266059SGregory Neil Shapiro return; 30340266059SGregory Neil Shapiro 304c2aa98e2SPeter Wemm if (tTd(35, 9)) 305c2aa98e2SPeter Wemm { 30640266059SGregory Neil Shapiro sm_dprintf("%sdefine(%s as ", 30740266059SGregory Neil Shapiro mac->mac_table[id] == NULL ? "" : "re", macname(id)); 30840266059SGregory Neil Shapiro xputs(value); 30940266059SGregory Neil Shapiro sm_dprintf(")\n"); 310c2aa98e2SPeter Wemm } 31140266059SGregory Neil Shapiro 31240266059SGregory Neil Shapiro if (mac->mac_rpool == NULL) 31340266059SGregory Neil Shapiro { 31440266059SGregory Neil Shapiro char *freeit = NULL; 31540266059SGregory Neil Shapiro 31640266059SGregory Neil Shapiro if (mac->mac_table[id] != NULL && 31740266059SGregory Neil Shapiro bitnset(id, mac->mac_allocated)) 31840266059SGregory Neil Shapiro freeit = mac->mac_table[id]; 31940266059SGregory Neil Shapiro 32040266059SGregory Neil Shapiro if (value == NULL || vclass == A_HEAP) 32140266059SGregory Neil Shapiro { 32240266059SGregory Neil Shapiro sm_heap_checkptr_tagged(value, file, line); 32340266059SGregory Neil Shapiro newvalue = value; 32440266059SGregory Neil Shapiro clrbitn(id, mac->mac_allocated); 32540266059SGregory Neil Shapiro } 32640266059SGregory Neil Shapiro else 32740266059SGregory Neil Shapiro { 32840266059SGregory Neil Shapiro newvalue = sm_strdup_tagged_x(value, file, line, 0); 32940266059SGregory Neil Shapiro setbitn(id, mac->mac_allocated); 33040266059SGregory Neil Shapiro } 33140266059SGregory Neil Shapiro mac->mac_table[id] = newvalue; 33240266059SGregory Neil Shapiro if (freeit != NULL) 33340266059SGregory Neil Shapiro sm_free(freeit); 33440266059SGregory Neil Shapiro } 33540266059SGregory Neil Shapiro else 33640266059SGregory Neil Shapiro { 33740266059SGregory Neil Shapiro if (value == NULL || vclass == A_PERM) 33840266059SGregory Neil Shapiro newvalue = value; 33940266059SGregory Neil Shapiro else 34040266059SGregory Neil Shapiro newvalue = sm_rpool_strdup_x(mac->mac_rpool, value); 34140266059SGregory Neil Shapiro mac->mac_table[id] = newvalue; 34240266059SGregory Neil Shapiro if (vclass == A_HEAP) 34340266059SGregory Neil Shapiro sm_free(value); 34440266059SGregory Neil Shapiro } 34506f25ae9SGregory Neil Shapiro 34606f25ae9SGregory Neil Shapiro #if _FFR_RESET_MACRO_GLOBALS 34740266059SGregory Neil Shapiro switch (id) 34806f25ae9SGregory Neil Shapiro { 34906f25ae9SGregory Neil Shapiro case 'j': 35040266059SGregory Neil Shapiro PSTRSET(MyHostName, value); 35106f25ae9SGregory Neil Shapiro break; 35206f25ae9SGregory Neil Shapiro } 35306f25ae9SGregory Neil Shapiro #endif /* _FFR_RESET_MACRO_GLOBALS */ 354c2aa98e2SPeter Wemm } 35540266059SGregory Neil Shapiro 35640266059SGregory Neil Shapiro /* 35740266059SGregory Neil Shapiro ** MACSET -- set a named macro to a value (low level) 35840266059SGregory Neil Shapiro ** 35940266059SGregory Neil Shapiro ** No fancy storage management; the caller takes full responsibility. 36040266059SGregory Neil Shapiro ** Often used with macget; see also macdefine. 36140266059SGregory Neil Shapiro ** 36240266059SGregory Neil Shapiro ** Parameters: 36340266059SGregory Neil Shapiro ** mac -- Macro table. 36440266059SGregory Neil Shapiro ** i -- Macro name, specified as an integer offset. 36540266059SGregory Neil Shapiro ** value -- Macro value: either NULL, or a string. 36640266059SGregory Neil Shapiro */ 36740266059SGregory Neil Shapiro 36840266059SGregory Neil Shapiro void 36940266059SGregory Neil Shapiro macset(mac, i, value) 37040266059SGregory Neil Shapiro MACROS_T *mac; 37140266059SGregory Neil Shapiro int i; 37240266059SGregory Neil Shapiro char *value; 37340266059SGregory Neil Shapiro { 37440266059SGregory Neil Shapiro if (i < 0 || i > MAXMACROID) 37540266059SGregory Neil Shapiro return; 37640266059SGregory Neil Shapiro 37740266059SGregory Neil Shapiro if (tTd(35, 9)) 37840266059SGregory Neil Shapiro { 37940266059SGregory Neil Shapiro sm_dprintf("macset(%s as ", macname(i)); 38040266059SGregory Neil Shapiro xputs(value); 38140266059SGregory Neil Shapiro sm_dprintf(")\n"); 38240266059SGregory Neil Shapiro } 38340266059SGregory Neil Shapiro mac->mac_table[i] = value; 38440266059SGregory Neil Shapiro } 38540266059SGregory Neil Shapiro 38640266059SGregory Neil Shapiro /* 387c2aa98e2SPeter Wemm ** MACVALUE -- return uninterpreted value of a macro. 388c2aa98e2SPeter Wemm ** 38940266059SGregory Neil Shapiro ** Does fancy path searching. 39040266059SGregory Neil Shapiro ** The low level counterpart is macget. 39140266059SGregory Neil Shapiro ** 392c2aa98e2SPeter Wemm ** Parameters: 393c2aa98e2SPeter Wemm ** n -- the name of the macro. 39440266059SGregory Neil Shapiro ** e -- envelope in which to start looking for the macro. 395c2aa98e2SPeter Wemm ** 396c2aa98e2SPeter Wemm ** Returns: 397c2aa98e2SPeter Wemm ** The value of n. 398c2aa98e2SPeter Wemm ** 399c2aa98e2SPeter Wemm ** Side Effects: 400c2aa98e2SPeter Wemm ** none. 401c2aa98e2SPeter Wemm */ 402c2aa98e2SPeter Wemm 403c2aa98e2SPeter Wemm char * 404c2aa98e2SPeter Wemm macvalue(n, e) 405c2aa98e2SPeter Wemm int n; 406c2aa98e2SPeter Wemm register ENVELOPE *e; 407c2aa98e2SPeter Wemm { 408193538b7SGregory Neil Shapiro n = bitidx(n); 40940266059SGregory Neil Shapiro if (e != NULL && e->e_mci != NULL) 41040266059SGregory Neil Shapiro { 41140266059SGregory Neil Shapiro register char *p = e->e_mci->mci_macro.mac_table[n]; 41240266059SGregory Neil Shapiro 41340266059SGregory Neil Shapiro if (p != NULL) 41440266059SGregory Neil Shapiro return p; 41540266059SGregory Neil Shapiro } 416c2aa98e2SPeter Wemm while (e != NULL) 417c2aa98e2SPeter Wemm { 41840266059SGregory Neil Shapiro register char *p = e->e_macro.mac_table[n]; 419c2aa98e2SPeter Wemm 420c2aa98e2SPeter Wemm if (p != NULL) 42106f25ae9SGregory Neil Shapiro return p; 422602a2b1bSGregory Neil Shapiro if (e == e->e_parent) 423602a2b1bSGregory Neil Shapiro break; 424c2aa98e2SPeter Wemm e = e->e_parent; 425c2aa98e2SPeter Wemm } 42640266059SGregory Neil Shapiro return GlobalMacros.mac_table[n]; 427c2aa98e2SPeter Wemm } 42840266059SGregory Neil Shapiro /* 429c2aa98e2SPeter Wemm ** MACNAME -- return the name of a macro given its internal id 430c2aa98e2SPeter Wemm ** 431c2aa98e2SPeter Wemm ** Parameter: 432c2aa98e2SPeter Wemm ** n -- the id of the macro 433c2aa98e2SPeter Wemm ** 434c2aa98e2SPeter Wemm ** Returns: 435c2aa98e2SPeter Wemm ** The name of n. 436c2aa98e2SPeter Wemm ** 437c2aa98e2SPeter Wemm ** Side Effects: 438c2aa98e2SPeter Wemm ** none. 439c2aa98e2SPeter Wemm */ 440c2aa98e2SPeter Wemm 441c2aa98e2SPeter Wemm char * 442c2aa98e2SPeter Wemm macname(n) 443c2aa98e2SPeter Wemm int n; 444c2aa98e2SPeter Wemm { 445c2aa98e2SPeter Wemm static char mbuf[2]; 446c2aa98e2SPeter Wemm 447193538b7SGregory Neil Shapiro n = bitidx(n); 448c2aa98e2SPeter Wemm if (bitset(0200, n)) 449c2aa98e2SPeter Wemm { 450c2aa98e2SPeter Wemm char *p = MacroName[n]; 451c2aa98e2SPeter Wemm 452c2aa98e2SPeter Wemm if (p != NULL) 453c2aa98e2SPeter Wemm return p; 454c2aa98e2SPeter Wemm return "***UNDEFINED MACRO***"; 455c2aa98e2SPeter Wemm } 456c2aa98e2SPeter Wemm mbuf[0] = n; 457c2aa98e2SPeter Wemm mbuf[1] = '\0'; 458c2aa98e2SPeter Wemm return mbuf; 459c2aa98e2SPeter Wemm } 46040266059SGregory Neil Shapiro /* 46140266059SGregory Neil Shapiro ** MACID_PARSE -- return id of macro identified by its name 462c2aa98e2SPeter Wemm ** 463c2aa98e2SPeter Wemm ** Parameters: 464c2aa98e2SPeter Wemm ** p -- pointer to name string -- either a single 465c2aa98e2SPeter Wemm ** character or {name}. 466c2aa98e2SPeter Wemm ** ep -- filled in with the pointer to the byte 467c2aa98e2SPeter Wemm ** after the name. 468c2aa98e2SPeter Wemm ** 469c2aa98e2SPeter Wemm ** Returns: 47040266059SGregory Neil Shapiro ** 0 -- An error was detected. 47140266059SGregory Neil Shapiro ** 1..255 -- The internal id code for this macro. 472c2aa98e2SPeter Wemm ** 473c2aa98e2SPeter Wemm ** Side Effects: 474c2aa98e2SPeter Wemm ** If this is a new macro name, a new id is allocated. 47540266059SGregory Neil Shapiro ** On error, syserr is called. 476c2aa98e2SPeter Wemm */ 477c2aa98e2SPeter Wemm 478c2aa98e2SPeter Wemm int 47940266059SGregory Neil Shapiro macid_parse(p, ep) 480c2aa98e2SPeter Wemm register char *p; 481c2aa98e2SPeter Wemm char **ep; 482c2aa98e2SPeter Wemm { 483c2aa98e2SPeter Wemm int mid; 484c2aa98e2SPeter Wemm register char *bp; 485065a643dSPeter Wemm char mbuf[MAXMACNAMELEN + 1]; 486c2aa98e2SPeter Wemm 487c2aa98e2SPeter Wemm if (tTd(35, 14)) 488c2aa98e2SPeter Wemm { 48940266059SGregory Neil Shapiro sm_dprintf("macid("); 490c2aa98e2SPeter Wemm xputs(p); 49140266059SGregory Neil Shapiro sm_dprintf(") => "); 492c2aa98e2SPeter Wemm } 493c2aa98e2SPeter Wemm 494c2aa98e2SPeter Wemm if (*p == '\0' || (p[0] == '{' && p[1] == '}')) 495c2aa98e2SPeter Wemm { 496c2aa98e2SPeter Wemm syserr("Name required for macro/class"); 497c2aa98e2SPeter Wemm if (ep != NULL) 498c2aa98e2SPeter Wemm *ep = p; 499c2aa98e2SPeter Wemm if (tTd(35, 14)) 50040266059SGregory Neil Shapiro sm_dprintf("NULL\n"); 501193538b7SGregory Neil Shapiro return 0; 502c2aa98e2SPeter Wemm } 503c2aa98e2SPeter Wemm if (*p != '{') 504c2aa98e2SPeter Wemm { 505c2aa98e2SPeter Wemm /* the macro is its own code */ 506c2aa98e2SPeter Wemm if (ep != NULL) 507c2aa98e2SPeter Wemm *ep = p + 1; 508c2aa98e2SPeter Wemm if (tTd(35, 14)) 50940266059SGregory Neil Shapiro sm_dprintf("%c\n", bitidx(*p)); 510193538b7SGregory Neil Shapiro return bitidx(*p); 511c2aa98e2SPeter Wemm } 512c2aa98e2SPeter Wemm bp = mbuf; 513065a643dSPeter Wemm while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1]) 514c2aa98e2SPeter Wemm { 515c2aa98e2SPeter Wemm if (isascii(*p) && (isalnum(*p) || *p == '_')) 516c2aa98e2SPeter Wemm *bp++ = *p; 517c2aa98e2SPeter Wemm else 518c2aa98e2SPeter Wemm syserr("Invalid macro/class character %c", *p); 519c2aa98e2SPeter Wemm } 520c2aa98e2SPeter Wemm *bp = '\0'; 521c2aa98e2SPeter Wemm mid = -1; 522c2aa98e2SPeter Wemm if (*p == '\0') 523c2aa98e2SPeter Wemm { 524c2aa98e2SPeter Wemm syserr("Unbalanced { on %s", mbuf); /* missing } */ 525c2aa98e2SPeter Wemm } 526c2aa98e2SPeter Wemm else if (*p != '}') 527c2aa98e2SPeter Wemm { 528c2aa98e2SPeter Wemm syserr("Macro/class name ({%s}) too long (%d chars max)", 52940266059SGregory Neil Shapiro mbuf, (int) (sizeof mbuf - 1)); 530c2aa98e2SPeter Wemm } 531c2aa98e2SPeter Wemm else if (mbuf[1] == '\0') 532c2aa98e2SPeter Wemm { 533c2aa98e2SPeter Wemm /* ${x} == $x */ 534193538b7SGregory Neil Shapiro mid = bitidx(mbuf[0]); 535c2aa98e2SPeter Wemm p++; 536c2aa98e2SPeter Wemm } 537c2aa98e2SPeter Wemm else 538c2aa98e2SPeter Wemm { 539c2aa98e2SPeter Wemm register STAB *s; 540c2aa98e2SPeter Wemm 541c2aa98e2SPeter Wemm s = stab(mbuf, ST_MACRO, ST_ENTER); 542c2aa98e2SPeter Wemm if (s->s_macro != 0) 543c2aa98e2SPeter Wemm mid = s->s_macro; 544c2aa98e2SPeter Wemm else 545c2aa98e2SPeter Wemm { 54606f25ae9SGregory Neil Shapiro if (NextMacroId > MAXMACROID) 547c2aa98e2SPeter Wemm { 54840266059SGregory Neil Shapiro syserr("Macro/class {%s}: too many long names", 54940266059SGregory Neil Shapiro mbuf); 550c2aa98e2SPeter Wemm s->s_macro = -1; 551c2aa98e2SPeter Wemm } 552c2aa98e2SPeter Wemm else 553c2aa98e2SPeter Wemm { 554c2aa98e2SPeter Wemm MacroName[NextMacroId] = s->s_name; 555c2aa98e2SPeter Wemm s->s_macro = mid = NextMacroId++; 556c2aa98e2SPeter Wemm } 557c2aa98e2SPeter Wemm } 558c2aa98e2SPeter Wemm p++; 559c2aa98e2SPeter Wemm } 560c2aa98e2SPeter Wemm if (ep != NULL) 561c2aa98e2SPeter Wemm *ep = p; 562193538b7SGregory Neil Shapiro if (mid < 0 || mid > MAXMACROID) 563193538b7SGregory Neil Shapiro { 564193538b7SGregory Neil Shapiro syserr("Unable to assign macro/class ID (mid = 0x%x)", mid); 565193538b7SGregory Neil Shapiro if (tTd(35, 14)) 56640266059SGregory Neil Shapiro sm_dprintf("NULL\n"); 567193538b7SGregory Neil Shapiro return 0; 568193538b7SGregory Neil Shapiro } 569c2aa98e2SPeter Wemm if (tTd(35, 14)) 57040266059SGregory Neil Shapiro sm_dprintf("0x%x\n", mid); 571c2aa98e2SPeter Wemm return mid; 572c2aa98e2SPeter Wemm } 57340266059SGregory Neil Shapiro /* 574c2aa98e2SPeter Wemm ** WORDINCLASS -- tell if a word is in a specific class 575c2aa98e2SPeter Wemm ** 576c2aa98e2SPeter Wemm ** Parameters: 577c2aa98e2SPeter Wemm ** str -- the name of the word to look up. 578c2aa98e2SPeter Wemm ** cl -- the class name. 579c2aa98e2SPeter Wemm ** 580c2aa98e2SPeter Wemm ** Returns: 58140266059SGregory Neil Shapiro ** true if str can be found in cl. 58240266059SGregory Neil Shapiro ** false otherwise. 583c2aa98e2SPeter Wemm */ 584c2aa98e2SPeter Wemm 585c2aa98e2SPeter Wemm bool 586c2aa98e2SPeter Wemm wordinclass(str, cl) 587c2aa98e2SPeter Wemm char *str; 588c2aa98e2SPeter Wemm int cl; 589c2aa98e2SPeter Wemm { 590c2aa98e2SPeter Wemm register STAB *s; 591c2aa98e2SPeter Wemm 592c2aa98e2SPeter Wemm s = stab(str, ST_CLASS, ST_FIND); 593193538b7SGregory Neil Shapiro return s != NULL && bitnset(bitidx(cl), s->s_class); 594c2aa98e2SPeter Wemm } 595