summaryrefslogtreecommitdiffstats
path: root/funtools/util/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'funtools/util/macro.c')
-rw-r--r--funtools/util/macro.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/funtools/util/macro.c b/funtools/util/macro.c
new file mode 100644
index 0000000..a96b3cc
--- /dev/null
+++ b/funtools/util/macro.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory
+ */
+
+/*
+ *
+ * macro.c -- macro expansion routines
+ *
+ */
+
+#include <macro.h>
+
+/* SAOMOD_CTYPE -- work around Slackware/RedHat incompatibility */
+#ifdef linux
+#ifdef isalnum
+#undef isalnum
+#define isalnum(c) (isalpha(c)||isdigit(c))
+#endif
+#endif
+
+#define BUFINC 5000
+
+/*
+ *
+ * Private Routines
+ *
+ *
+ */
+
+/*
+ *
+ * AddString -- add a string to a buffer
+ *
+ */
+#ifdef ANSI_FUNC
+static void
+AddString(char **buf, int *blen, int *maxlen, char *str)
+#else
+static void AddString(buf, blen, maxlen, str)
+ char **buf;
+ int *blen;
+ int *maxlen;
+ char *str;
+#endif
+{
+ int slen;
+
+ if( !str || !*str ) return;
+ slen = strlen(str) + 1;
+ while( (*blen + slen) >= *maxlen ){
+ *maxlen += BUFINC;
+ *buf = (char *)realloc(*buf, *maxlen);
+ }
+ strcat(*buf, str);
+ *blen += slen;
+}
+
+/*
+ *
+ * AddChar -- add a single char to a buffer
+ *
+ */
+#ifdef ANSI_FUNC
+static void
+AddChar(char **buf, int *blen, int *maxlen, int c)
+#else
+static void AddChar(buf, blen, maxlen, c)
+ char **buf;
+ int *blen;
+ int *maxlen;
+ int c;
+#endif
+{
+ char tbuf[2];
+
+ tbuf[0] = (char)c;
+ tbuf[1] = '\0';
+ AddString(buf, blen, maxlen, tbuf);
+}
+
+/*
+ *
+ * LookupKeywords -- lookup a name in a list fo keywords and
+ * return the associated value.
+ * (Should use quarks ...)
+ *
+ */
+#ifdef ANSI_FUNC
+static char *
+LookupKeywords(char *name, char **keyword, char **value, int nkey)
+#else
+static char *LookupKeywords(name, keyword, value, nkey)
+ char *name;
+ char **keyword;
+ char **value;
+ int nkey;
+#endif
+{
+ int i;
+ for(i=0; i<nkey; i++){
+ if( keyword[i] && !strcmp(name, keyword[i]) )
+ return(value[i]);
+ }
+ return(NULL);
+}
+
+/*
+ *
+ * Public Routines
+ *
+ *
+ */
+
+/*
+ *
+ * ExpandMacro -- expand a macro using a client's callback
+ * returns: expanded macro as an allocated string
+ *
+ */
+#ifdef ANSI_FUNC
+char *
+ExpandMacro(char *icmd, char **keyword, char **value, int nkey,
+ MacroCall client_callback, void *client_data)
+#else
+char *ExpandMacro(icmd, keyword, value, nkey, client_callback, client_data)
+ char *icmd;
+ char **keyword;
+ char **value;
+ int nkey;
+ MacroCall client_callback;
+ void *client_data;
+#endif
+{
+ int i, j;
+ int maxlen;
+ char brace;
+ char *result;
+ char tbuf[1000];
+ char tbuf1[1000];
+ char *s;
+ char *ip;
+ char *mip;
+
+ /* make a new string using the command as a base, but substituting
+ for "$" values as needed */
+ result = (char *)malloc(BUFINC+1);
+ maxlen = BUFINC;
+ *result = '\0';
+ for(i=0, ip=icmd; *ip; ip++){
+ if( *ip != '$' ){
+ AddChar(&result, &i, &maxlen, (int)*ip);
+ }
+ else{
+ /* save beginning of macro */
+ mip = ip;
+ /* skip past '$' */
+ ip++;
+ /* check for brace mode */
+ if( *ip == '{' ){
+ brace = '{';
+ ip++;
+ }
+ else if( *ip == '(' ){
+ brace = '(';
+ ip++;
+ }
+ else
+ brace = '\0';
+ /* get variable up to next non-alpha character or close brace */
+ for(*tbuf='\0', j=0; *ip; ip++ ){
+ /* if we are in brace mode, look for trailing brace */
+ if( brace && *ip == (brace == '(' ? ')' : '}') ){
+ ip++;
+ break;
+ }
+ /* else look for a non-alpha character */
+ else if( !isalnum((int)*ip) && *ip != '_'){
+ break;
+ }
+ else{
+ tbuf[j++] = *ip;
+ tbuf[j] = '\0';
+ }
+ }
+ /* back up so the outer loop adds this delimiting char to the output */
+ ip--;
+ /* search for keyword from the list */
+ if( (nkey > 0) &&
+ (s=LookupKeywords(tbuf, keyword, value, nkey)) != NULL ){
+ AddString(&result, &i, &maxlen, s);
+ }
+ /* execute the client routine to expand macros */
+ else if( (client_callback != NULL) &&
+ ((s=(*client_callback)(tbuf, client_data)) != NULL) ){
+ AddString(&result, &i, &maxlen, s);
+ }
+ /* look for an environment variable */
+ else if( (s = (char *)getenv(tbuf)) != NULL ){
+ AddString(&result, &i, &maxlen, s);
+ }
+ /* if we don't recognize this macro, put it back onto the string */
+ else{
+ int len;
+ len = ip - mip + 1;
+ strncpy(tbuf1, mip, len);
+ tbuf1[len] = '\0';
+ AddString(&result, &i, &maxlen, tbuf1);
+ }
+ }
+ }
+ /* null terminate and save the string */
+ result[i] = '\0';
+ result = (char *)realloc(result, i+1);
+ return(result);
+}
+