Corrected the handling of parameters inside and outside a subcircuit
call.
diff --git a/common/spectre_to_spice.py b/common/spectre_to_spice.py
index ccaea96..c522367 100755
--- a/common/spectre_to_spice.py
+++ b/common/spectre_to_spice.py
@@ -27,25 +27,27 @@
 # If inside a subcircuit, remove the keyword "parameters".  If outside,
 # change it to ".param"
 
-def parse_param_line(line, inparam, insub):
+def parse_param_line(line, inparam, insub, iscall, ispassed):
 
     # Regexp patterns
     parm1rex = re.compile('[ \t]*parameters[ \t]*(.*)')
     parm2rex = re.compile('[ \t]*params:[ \t]*(.*)')
-    parm3rex = re.compile('\+[ \t]*(.*)')
+    parm3rex = re.compile('[ \t]*\+[ \t]*(.*)')
     parm4rex = re.compile('[ \t]*([^= \t]+)[ \t]*=[ \t]*([^ \t]+)[ \t]*(.*)')
     parm5rex = re.compile('[ \t]*([^= \t]+)[ \t]*(.*)')
+    rtok = re.compile('([^ \t\n]+)[ \t]*(.*)')
 
     fmtline = []
-    iscdl = False
     
-    if inparam:
+    if iscall:
+        rest = line
+    elif inparam:
         pmatch = parm3rex.match(line)
         if pmatch:
             fmtline.append('+')
             rest = pmatch.group(1)
         else:
-            return ''
+            return '', ispassed
     else:
         pmatch = parm1rex.match(line)
         if pmatch:
@@ -60,62 +62,96 @@
                 if insub:
                     fmtline.append('+')
                 else:
-                    return ''
+                    return '', ispassed
                 rest = pmatch.group(1)
-                iscdl = True
             else:
-                return ''
+                return '', ispassed
 
     while rest != '':
         pmatch = parm4rex.match(rest)
         if pmatch:
+            if ispassed:
+                # End of passed parameters.  Break line and generate ".param"
+                ispassed = False
+                fmtline.append('\n.param ')
+
             fmtline.append(pmatch.group(1))
             fmtline.append('=')
             value = pmatch.group(2)
             rest = pmatch.group(3)
 
+            # Watch for spaces in expressions (have they no rules??!)
+            # as indicated by something after a space not being an
+            # alphabetical character (parameter name) or '$' (comment)
+
+            needmore = False
+            while rest != '':
+                rmatch = rtok.match(rest)
+                if rmatch:
+                    expch = rmatch.group(1)[0]
+                    if (expch.isalpha() or expch == '$') and not needmore:
+                        break
+                    else:
+                        needmore = False
+                        value += rmatch.group(1)
+                        rest = rmatch.group(2)
+                        expch = rmatch.group(1).strip()
+                        if expch in '+-*/(){}^~!':
+                            needmore = True
+                else:
+                    break
+
             if is_number(value):
                 fmtline.append(value)
             else:
                 fmtline.append('{' + value + '}')
 
-            # These parameter sub-expressions are related to
-            # monte carlo simulation and are incompatible with
-            # ngspice.  So put them in an in-line comment
+            # These parameter sub-expressions are related to monte carlo
+            # simulation and are incompatible with ngspice.  So put them
+            # in an in-line comment.  Avoid double-commenting things that
+            # were already in-line comments.
 
             if rest != '':
                 nmatch = parm4rex.match(rest)
                 if not nmatch:
-                    fmtline.append(' $ ' + rest.replace(' ', '').replace('\t', ''))
+                    if rest.lstrip().startswith('$ '):
+                        fmtline.append(rest)
+                    elif rest.strip() != '':
+                        fmtline.append(' $ ' + rest.replace(' ', '').replace('\t', ''))
                     rest = ''
-        elif iscdl:
+        else:
             # Match to a CDL subckt parameter that does not have an '=' and so
-            # assumes that the parameter is always passed.  That is not legal SPICE,
-            # so supply a default value of 1.
+            # assumes that the parameter is always passed, and therefore must
+	    # be part of the .subckt line.  A parameter without a value is not
+            # legal SPICE, so supply a default value of 1.
             pmatch = parm5rex.match(rest)
             if pmatch:
                 fmtline.append(pmatch.group(1) + '=1')
+                ispassed = True
                 rest = pmatch.group(2)
-        else:
-            break
+            else:
+                break
 
-    return ' '.join(fmtline)
+    return ' '.join(fmtline), ispassed
 
 def convert_file(in_file, out_file):
 
     # Regexp patterns
     statrex = re.compile('[ \t]*statistics[ \t]*\{(.*)')
     simrex = re.compile('[ \t]*simulator[ \t]+([^= \t]+)[ \t]*=[ \t]*(.+)')
-    insubrex = re.compile('[ \t]*inline[ \t]+subckt[ \t]+([^ \t]+)[ \t]*\(([^)]*)')
-    cdlsubrex = re.compile('\.subckt[ \t]+([^ \t]+)[ \t]*\(([^)]*)')
+    insubrex = re.compile('[ \t]*inline[ \t]+subckt[ \t]+([^ \t\(]+)[ \t]*\(([^)]*)')
+    cdlsubrex = re.compile('\.?subckt[ \t]+([^ \t\(]+)[ \t]*\(([^)]*)')
     endsubrex = re.compile('[ \t]*ends[ \t]+(.+)')
+    endonlysubrex = re.compile('[ \t]*ends[ \t]*')
     modelrex = re.compile('[ \t]*model[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+\{(.*)')
+    cdlmodelrex = re.compile('[ \t]*model[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+(.*)')
     binrex = re.compile('[ \t]*([0-9]+):[ \t]+type[ \t]*=[ \t]*(.*)')
     shincrex = re.compile('\.inc[ \t]+')
 
     stdsubrex = re.compile('\.subckt[ \t]+([^ \t]+)[ \t]+([^ \t]*)')
     stdmodelrex = re.compile('\.model[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+(.*)')
     stdendsubrex = re.compile('\.ends[ \t]+(.+)')
+    stdendonlysubrex = re.compile('\.ends[ \t]*')
 
     # Devices (resistor, capacitor, subcircuit as resistor or capacitor)
     caprex = re.compile('c([^ \t]+)[ \t]*\(([^)]*)\)[ \t]*capacitor[ \t]*(.*)', re.IGNORECASE)
@@ -123,13 +159,18 @@
     cdlrex = re.compile('[ \t]*([crdlmqx])([^ \t]+)[ \t]*\(([^)]*)\)[ \t]*([^ \t]+)[ \t]*(.*)', re.IGNORECASE)
 
     with open(in_file, 'r') as ifile:
-        speclines = ifile.read().splitlines()
+        try:
+            speclines = ifile.read().splitlines()
+        except:
+            print('Failure to read ' + in_file + '; not an ASCII file?')
+            return
 
     insub = False
     inparam = False
     inmodel = False
     inpinlist = False
     isspectre = False
+    ispassed = False
     spicelines = []
     calllines = []
     modellines = []
@@ -141,7 +182,7 @@
 
     for line in speclines:
 
-        # Item 1.  C++-style // comments get replae with * comment character
+        # Item 1a.  C++-style // comments get replaced with * comment character
         if line.strip().startswith('//'):
             # Replace the leading "//" with SPICE-style comment "*".
             if modellines != []:
@@ -152,6 +193,12 @@
                 spicelines.append(line.strip().replace('//', '*', 1))
             continue
 
+        # Item 1b.  In-line C++-style // comments get replaced with $ comment character
+        elif ' //' in line:
+            line = line.replace(' //', ' $ ', 1) 
+        elif '\t//' in line:
+            line = line.replace('\t//', '\t$ ', 1) 
+
         # Item 2.  Handle SPICE-style comment lines
         if line.strip().startswith('*'):
             if modellines != []:
@@ -167,10 +214,11 @@
             contline = True
         else:
             contline = False
-            if inparam:
-                inparam = False 
-            if inpinlist:
-                inpinlist = False 
+            if line.strip() != '':
+                if inparam:
+                    inparam = False 
+                if inpinlist:
+                    inpinlist = False 
 
         # Item 3.  Handle blank lines like comment lines
         if line.strip() == '':
@@ -201,7 +249,7 @@
         if contline:
             if inparam:
                 # Continue handling parameters
-                fmtline = parse_param_line(line, inparam, insub)
+                fmtline, ispassed = parse_param_line(line, inparam, insub, False, ispassed)
                 if fmtline != '':
                     if modellines != []:
                         modellines.append(fmtline)
@@ -225,7 +273,7 @@
 
         # If inside a subcircuit, remove "parameters".  If outside,
         # change it to ".param"
-        fmtline = parse_param_line(line, inparam, insub)
+        fmtline, ispassed = parse_param_line(line, inparam, insub, False, ispassed)
         if fmtline != '':
             inparam = True
             spicelines.append(fmtline)
@@ -240,10 +288,15 @@
                 continue
 
         # model---not sure if it is always inside an inline subcircuit
+        iscdl = False
         if isspectre:
             mmatch = modelrex.match(line)
+            if not mmatch:
+                mmatch = cdlmodelrex.match(line)
+                iscdl = True
         else:
             mmatch = stdmodelrex.match(line)
+
         if mmatch:
             modname = mmatch.group(1)
             modtype = mmatch.group(2)
@@ -253,20 +306,25 @@
                 inmodel = 1
                 # Continue to "if inmodel == 1" block below
             else:
-                if not isspectre:
-                    modellines.append(line)
+                fmtline, ispassed = parse_param_line(mmatch.group(3), True, False, True, ispassed)
+                modellines.append('.model ' + mmatch.group(1) + ' ' + mmatch.group(2) + ' ' + fmtline)
+                if fmtline != '':
+                    inparam = True
+
                 inmodel = 2
                 continue
 
         if not insub:
             # Things to parse if not in a subcircuit
+            imatch = insubrex.match(line) if isspectre else None
 
-            if isspectre:
-                imatch = insubrex.match(line)
-            else:
-                # Check for CDL format .subckt lines first
+            if not imatch:
+                # Check for spectre format subckt or CDL format .subckt lines
                 imatch = cdlsubrex.match(line)
-                if not imatch:
+
+            if not imatch:
+                if not isspectre:
+                    # Check for standard SPICE format .subckt lines
                     imatch = stdsubrex.match(line)
 
             if imatch:
@@ -278,6 +336,7 @@
                     inmodel = False
 
                 insub = True
+                ispassed = True
                 subname = imatch.group(1)
                 if isspectre:
                     devrex = re.compile(subname + '[ \t]*\(([^)]*)\)[ \t]*([^ \t]+)[ \t]*(.*)', re.IGNORECASE)
@@ -307,13 +366,23 @@
             else:
                 if isspectre:
                     ematch = endsubrex.match(line)
+                    if not ematch:
+                        ematch = endonlysubrex.match(line)
                 else:
                     ematch = stdendsubrex.match(line)
+                    if not ematch:
+                        ematch = stdendonlysubrex.match(line)
+
                 if ematch:
-                    if ematch.group(1) != subname:
-                        print('Error:  "ends" name does not match "subckt" name!')
-                        print('"ends" name = ' + ematch.group(1))
-                        print('"subckt" name = ' + subname)
+                    try:
+                        endname = ematch.group(1).strip()
+                    except:
+                        pass
+                    else:
+                        if endname != subname and endname != '':
+                            print('Error:  "ends" name does not match "subckt" name!')
+                            print('"ends" name = ' + ematch.group(1).strip())
+                            print('"subckt" name = ' + subname)
                     if len(calllines) > 0:
                         line = calllines[0]
                         if modtype.startswith('bsim'):
@@ -340,14 +409,15 @@
                         spicelines.append(line)
                     calllines = []
 
-                    spicelines.append('.ends ' + subname)
-
-                    # Now add the .model after the subcircuit definition
+                    # Now add any in-circuit models
                     spicelines.append('')
                     for line in modellines:
                         spicelines.append(line)
                     modellines = []
                     
+                    # Complete the subcircuit definition
+                    spicelines.append('.ends ' + subname)
+
                     insub = False
                     inmodel = False
                     subname = ''
@@ -362,7 +432,7 @@
             # Check for devices R and C.
             dmatch = caprex.match(line)
             if dmatch:
-                fmtline = parse_param_line(dmatch.group(3), True, insub)
+                fmtline, ispassed = parse_param_line(dmatch.group(3), True, insub, True, ispassed)
                 if fmtline != '':
                     inparam = True
                     spicelines.append('c' + dmatch.group(1) + ' ' + dmatch.group(2) + ' ' + fmtline)
@@ -373,7 +443,7 @@
 
             dmatch = resrex.match(line)
             if dmatch:
-                fmtline = parse_param_line(dmatch.group(3), True, insub)
+                fmtline, ispassed = parse_param_line(dmatch.group(3), True, insub, True, ispassed)
                 if fmtline != '':
                     inparam = True
                     spicelines.append('r' + dmatch.group(1) + ' ' + dmatch.group(2) + ' ' + fmtline)
@@ -384,6 +454,7 @@
 
             cmatch = cdlrex.match(line)
             if cmatch:
+                ispassed = False
                 devtype = cmatch.group(1)
                 devmodel = cmatch.group(4)
 
@@ -401,7 +472,7 @@
                     # model is a resistor and not a subcircuit.
                     devtype = 'r'
 
-                fmtline = parse_param_line(cmatch.group(5), True, insub)
+                fmtline, ispassed = parse_param_line(cmatch.group(5), True, insub, True, ispassed)
                 if fmtline != '':
                     inparam = True
                     spicelines.append(devtype + cmatch.group(2) + ' ' + cmatch.group(3) + ' ' + devmodel + ' ' + fmtline)
@@ -414,7 +485,7 @@
           
             dmatch = devrex.match(line)
             if dmatch:
-                fmtline = parse_param_line(dmatch.group(3), True, insub)
+                fmtline, ispassed = parse_param_line(dmatch.group(3), True, insub, True, ispassed)
                 if fmtline != '':
                     inparam = True
                     calllines.append(subname + ' ' + dmatch.group(1) + ' ' + dmatch.group(2) + ' ' + fmtline)
@@ -447,7 +518,7 @@
                 continue
 
             else:
-                fmtline = parse_param_line(line, True, True)
+                fmtline, ispassed = parse_param_line(line, True, True, False, ispassed)
                 if fmtline != '':
                     modellines.append(fmtline)
                     continue