--- freem/src/expr.c	2025/03/09 19:14:24	1.5
+++ freem/src/expr.c	2025/03/30 01:36:58	1.11
@@ -1,5 +1,5 @@
 /*
- *   $Id: expr.c,v 1.5 2025/03/09 19:14:24 snw Exp $
+ *   $Id: expr.c,v 1.11 2025/03/30 01:36:58 snw Exp $
  *    expression parser
  *
  *  
@@ -24,6 +24,24 @@
  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
  *
  *   $Log: expr.c,v $
+ *   Revision 1.11  2025/03/30 01:36:58  snw
+ *   Make it easier to bring back fma_gedit, fix double-free in global handler, limit $CHAR to 7-bit ASCII
+ *
+ *   Revision 1.10  2025/03/24 04:13:11  snw
+ *   Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
+ *
+ *   Revision 1.9  2025/03/24 01:32:22  snw
+ *   Guard declaration of time function in expr.c for portability
+ *
+ *   Revision 1.8  2025/03/22 04:47:18  snw
+ *   Silently truncate long names in STRING exprs when  evaluates to an obsolete MDC standard
+ *
+ *   Revision 1.7  2025/03/22 03:39:23  snw
+ *   Fix reverse query polyfill call-in from C side and make NAME exprs silently truncate long names in obsolete MDC dialects
+ *
+ *   Revision 1.6  2025/03/22 03:05:19  snw
+ *   Comply with X11-96/13 portable length of names
+ *
  *   Revision 1.5  2025/03/09 19:14:24  snw
  *   First phase of REUSE compliance and header reformat
  *
@@ -129,7 +147,7 @@
 #define GET               'Y'
 #define GETX              ':'
 
-#if !defined(__OpenBSD__) && !defined(_AIX) && !defined(__osf__) && !defined(MSDOS) && !defined(__vax__)
+#if !defined(__OpenBSD__) && !defined(_AIX) && !defined(__osf__) && !defined(MSDOS) && !defined(__vax__) && !defined(__OS2__)
 long    time ();
 #endif
 void cond_round (char *a, int digits);
@@ -173,6 +191,15 @@ void expr (short extyp)
     volatile int ch = 0;
     
     short   group;          /* flag to scan grouped patterns */
+
+    int  max_namlen = 255;
+
+    if ((rtn_dialect () == D_MDS) || (rtn_dialect () == D_M5) || (rtn_dialect () == D_FREEM)) {
+        max_namlen = 255;
+    }
+    else {
+        max_namlen = 8;
+    }
     
 #ifdef DEBUG_NEWPTR
     int loop;
@@ -201,14 +228,36 @@ void expr (short extyp)
                       (((ch == '/' && varnam[i - 1] != '/') ||
                         (ch == '%' && varnam[i - 1] == '/')) &&
                        (varnam[1] == '.' || varnam[1] == '/'))))) || (f != '^') && (ch == '.')) {
-                
-                varnam[i++] = ch;
 
-                
+                if ((i + 1) <= max_namlen) {
+                    varnam[i++] = ch;
+                }
+                else {
+                    if ((rtn_dialect () == D_M77) ||
+                        (rtn_dialect () == D_M84) ||
+                        (rtn_dialect () == D_M90) ||
+                        (rtn_dialect () == D_M95)) {
+                        /* silently truncate... yeah, the standard is stupid af */
+                        continue;
+                    }
+                    else {
+                        merr_raise (M56);
+                        return;
+                    }
+                }                
                 
             }
 
-            varnam[i] = EOL;            
+            varnam[i] = EOL;
+
+            #if 0
+            {
+                char gooby[256];
+                stcpy (gooby, varnam);
+                stcnv_m2c (gooby);
+                printf ("name = '%s'\r\n", gooby);
+            }
+            #endif
             
             if (ch == '(') {        /* it's an array */
                 
@@ -329,8 +378,23 @@ scan_name:
                     merr_raise (INVEXPR);
                     return;
                 }
-                
-                varnam[i++] = ch;
+
+                if ((i + 1) <= max_namlen) {
+                    varnam[i++] = ch;
+                }
+                else {
+                    if ((rtn_dialect () == D_M77) ||
+                        (rtn_dialect () == D_M84) ||
+                        (rtn_dialect () == D_M90) ||
+                        (rtn_dialect () == D_M95)) {
+                        /* silently truncate... yeah, the standard is stupid af */
+                        continue;
+                    }
+                    else {
+                        merr_raise (M56);
+                        return;
+                    }
+                }                
 
                 lastch = ch;
             }
@@ -346,7 +410,24 @@ scan_name:
         else {          /* local variable name */
 
             while (isalnum (ch = *++codptr)) {
-                varnam[i++] = ch;
+                
+                if ((i + 1) <= max_namlen) {
+                    varnam[i++] = ch;
+                }
+                else {
+                    if ((rtn_dialect () == D_M77) ||
+                        (rtn_dialect () == D_M84) ||
+                        (rtn_dialect () == D_M90) ||
+                        (rtn_dialect () == D_M95)) {
+                        /* silently truncate... yeah, the standard is stupid af */
+                        continue;
+                    }
+                    else {
+                        merr_raise (M56);
+                        return;
+                    }
+                }                
+                
             }
         
             varnam[i] = EOL;
@@ -486,7 +567,7 @@ var1:
 
                 case 'd':           /* $DATA */
                     
-                    ch = dat;
+                    ch = fra_dat;
 
 glv_fcn:
 
@@ -1600,7 +1681,9 @@ uparrow:
 
                 case 'c':           /* $CHARACTER */
 
-                    {
+                    {                        
+                        char chrtmp[256];
+                        long pnum;
                         short l, l1, m, n;
 
                         l1 = f;
@@ -1611,6 +1694,15 @@ uparrow:
                         n = 1;
                         l = 0;
 
+                        stcpy (chrtmp, a);
+                        stcnv_m2c (chrtmp);
+                        pnum = atol (chrtmp);
+
+                        if (pnum > 127) {
+                            merr_raise (MXNUM);
+                            return;
+                        }
+                        
                         for (;;) {
                             
                             if ((ch = a[i++]) == EOL) {
@@ -2219,7 +2311,7 @@ f20:
                         stcnv_c2m (qryarg_ext);
 
                         /* put the $QUERY argument into the local variable %INT.REVQ */
-                        symtab (set_sym, "%INT.REVQ\201\201", qryarg_ext);
+                        symtab (set_sym, "%INTREVQ\201\201", qryarg_ext);
 
                         /* set up for calling into polyfill wrapper */
                         code[0] = '\201';