Hi all,

I had a go at attempting to implement if-elsif-else-endif syntax for
FVWM so I can do things like this in my .fvwm2rc file:

(Much more intuitive/maintainable than using PipeRead.)


if xdpyinfo | /bin/grep -q XINERAMA
        Echo "dual head system!"
        Xinerama on
        XineramaPrimaryScreen 0
        DeskTopSize 4x1
else
        Echo "NOT a dual head system."
        DeskTopSize 6x1
endif


if [[ $(hostname) = "hamlet.denmark.org" ]]
        Echo "This is SCoTT's home system"
elsif hostname | grep -q aao
        Echo "This is SCoTT's work system"
endif


if [ -f someSlackwareFile ]
        Echo "This is a Slackware system."
elsif [ -f /etc/someDebianFile ]
        Echo "This is a Debian system."
elsif [ -f /etc/redhat-release ]
        Echo "This is a RedHat system."
else
        Echo "No idea what system this is."
endif


if [ $(cat /proc/meminfo | grep ^MemTotal | tr -s ' ' | cut -f2 -d' ') -gt 
500000 ]
        Echo "You have more than 0.5GB of RAM"
else
        Echo "You need to upgrade."
endif

Unfortunately I don't know of a way to make this work with FvwmConsole.

Does anyone have any comments, suggestions, criticism, encouragement?

SCoTT. :)
Index: fvwm/read.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/read.c,v
retrieving revision 1.60
diff -u -r1.60 read.c
--- fvwm/read.c 29 Jun 2003 19:53:23 -0000      1.60
+++ fvwm/read.c 29 Apr 2004 10:44:04 -0000
@@ -114,25 +114,16 @@
        return curr_read_dir;
 }
 
-
-/*
- * Read and execute each line from stream.
- */
-void run_command_stream(
-       cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc)
+/* __run_command_stream() - utility function for run_command_stream(). */
+void __run_command_stream(
+       cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc,
+       Bool bInIf, Bool bIfTrue)
 {
-       char *tline;
+       char *tline, *tmp, *func = "__run_command_stream", *cond;
        char line[1024];
+       Bool bIgnoreSection = !bIfTrue;
 
-       /* Set close-on-exec flag */
-       fcntl(fileno(f), F_SETFD, 1);
-
-       /* Update window decorations in case we were called from a menu that
-        * has now popped down. */
-       handle_all_expose();
-
-       tline = fgets(line, (sizeof line) - 1, f);
-       while (tline)
+       while (NULL != (tline = fgets(line, (sizeof line) - 1, f)))
        {
                int l;
                while (tline && (l = strlen(line)) < sizeof(line) && l >= 2 &&
@@ -150,6 +141,63 @@
                {
                        tline[l - 1] = '\0';
                }
+               /* remove leading whitespace */
+               tline = SkipSpaces(tline, NULL, 0);
+               /* ignore blank lines & comments. */
+               if (tline == NULL || tline[0] == '\0' || tline[0] == '#')
+                       continue;
+
+               tmp = tline;
+               tmp = PeekToken(tmp, &cond);
+               if (strcasecmp(tmp, "if") == 0)
+               {
+                       // fvwm_msg(DBG, func, "if-cmd=<%s>", cond);
+                       bIfTrue = !system(cond);
+                       // use recursion to allow nested if-statements.
+                       __run_command_stream(cond_rc, f, exc, True, bIfTrue);
+                       // at this point the complete if-statement has been 
handled.
+                       // ie. we've parsed the file all the way through to the
+                       // matching "endif".
+                       continue;
+               }
+               else if (strcasecmp(tmp, "elsif") == 0)
+               {
+                       if (!bInIf)
+                               fvwm_msg(ERR, func, "\"elsif\" not within 
if-statement");
+                       if (bIfTrue)
+                               bIgnoreSection = True;
+                       else
+                       {
+                               // fvwm_msg(DBG, func, "elsif-cmd=<%s>", cond);
+                               bIfTrue = !system(cond);
+                               bIgnoreSection = !bIfTrue;
+                       }
+                       continue;
+               }
+               else if (strcasecmp(tmp, "else") == 0)
+               {
+                       if (!bInIf)
+                               fvwm_msg(ERR, func, "\"else\" not within 
if-statement");
+                       if (bIfTrue)
+                               bIgnoreSection = True;
+                       else
+                       {
+                               bIfTrue = True;
+                               bIgnoreSection = False;
+                       }
+                       continue;
+               }
+               else if (strcasecmp(tmp, "endif") == 0)
+               {
+                       if (!bInIf)
+                               fvwm_msg(ERR, func, "\"endif\" not within 
if-statement");
+                       else
+                               return;
+               }
+
+               if (bInIf && bIgnoreSection)
+                       continue;
+
                if (debugging)
                {
                        fvwm_msg(
@@ -158,12 +206,26 @@
                        exc->m.modnum, tline);
                }
                execute_function(cond_rc, exc, tline, 0);
-               tline = fgets(line, (sizeof line) - 1, f);
        }
 
        return;
 }
 
+/*
+ * Read and execute each line from stream.
+ */
+void run_command_stream(
+       cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc)
+{
+       /* Set close-on-exec flag */
+       fcntl(fileno(f), F_SETFD, 1);
+
+       /* Update window decorations in case we were called from a menu that
+        * has now popped down. */
+       handle_all_expose();
+
+       __run_command_stream(cond_rc, f, exc, False, False);
+}
 
 /**
  * Parse the action string.  We expect a filename, and optionally,

Reply via email to