Some fixes and enhancements to the two helper scripts change_gds_string.py
and find_gds_prefix.py.  The latter script is probably useless because
running the Linux "strings" command is much faster.  The former script
can now be used with multiple string-replacement pairs in one pass, and
has the option "-verbatim" to look for exact string matches only, rather
than the usual partial string match that comes from using regsub or
the string "replace" method in python.
diff --git a/Makefile.in b/Makefile.in
index cb4286b..06bb94a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -87,6 +87,9 @@
 		mkdir -p @prefix@/pdk/bin/ ;\
 		cp common/cleanup_unref.py @prefix@/pdk/bin/ ;\
 		cp common/soc_floorplanner.py @prefix@/pdk/bin/ ;\
+		cp common/change_gds_cell.py @prefix@/pdk/bin/ ;\
+		cp common/find_gds_prefix.py @prefix@/pdk/bin/ ;\
+		cp common/change_gds_string.py @prefix@/pdk/bin/ ;\
 		${CPP} -DPREFIX=@prefix@ common/create_project.py \
 			@prefix@/pdk/bin/create_project.py ;\
 		echo "Common install:  Done." ;\
diff --git a/VERSION b/VERSION
index f6e5575..81e489d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.173
+1.0.174
diff --git a/common/change_gds_string.py b/common/change_gds_string.py
old mode 100755
new mode 100644
index accbc50..7ebfb28
--- a/common/change_gds_string.py
+++ b/common/change_gds_string.py
@@ -6,13 +6,15 @@
 # string around the search text, and adjusting the record bounds accordingly.
 
 import os
+import re
 import sys
 
 def usage():
-    print('change_gds_string.py <old_string> <new_string> <path_to_gds_in> [<path_to_gds_out>]')
+    print('change_gds_string.py <old_string> <new_string> [...] <path_to_gds_in> [<path_to_gds_out>]')
 
 if __name__ == '__main__':
-    debug = False
+    debug = 0
+    verbatim = False
 
     if len(sys.argv) == 1:
         print("No options given to change_gds_string.py.")
@@ -28,23 +30,38 @@
         else:
             arguments.append(option)
 
-    if len(arguments) < 3 or len(arguments) > 4:
+    if len(arguments) < 3:
         print("Wrong number of arguments given to change_gds_string.py.")
         usage()
         sys.exit(0)
 
-    if '-debug' in optionlist:
-        debug = True
+    for option in optionlist:
+        opval = option.split('=')
+        if opval[0] == '-debug':
+            if len(opval) == 2:
+                debug = int(opval[1])
+            else:
+                debug = 1
+        elif opval[0] == '-verbatim':
+            verbatim = True
 
-    oldstring = arguments[0]
-    newstring = arguments[1]
-    source = arguments[2]
-
-    # If only three arguments are provided, then overwrite the source file.
-    if len(arguments) == 4:
-        dest = arguments[3]
+    # If next-to-last argument is a valid path, then the last argument should
+    # be the path to GDS out.  Otherwise, overwrite the source file.
+    
+    if os.path.isfile(arguments[-2]):
+        dest = arguments[-1]
+        source = arguments[-2]
+        oldstrings = arguments[0:-2:2]
+        newstrings = arguments[1:-2:2]
     else:
-        dest = arguments[2]
+        dest = arguments[-1]
+        source = arguments[-1]
+        oldstrings = arguments[0:-1:2]
+        newstrings = arguments[1:-1:2]
+
+    if len(oldstrings) != len(newstrings):
+        print('Error:  List of strings and replacements is not in pairs.')
+        sys.exit(1)
 
     sourcedir = os.path.split(source)[0]
     gdsinfile = os.path.split(source)[1]
@@ -61,11 +78,15 @@
 
     recordtypes = ['libname', 'strname', 'sname', 'string']
     recordfilter = [2, 6, 18, 25]
-    bsearch = bytes(oldstring, 'ascii')
-    brep = bytes(newstring, 'ascii')
+    bsearchlist = list(bytes(item, 'ascii') for item in oldstrings)
+    breplist = list(bytes(item, 'ascii') for item in newstrings)
+
+    if debug > 1:
+        print('Search list = ' + str(bsearchlist))
+        print('Replace list = ' + str(breplist))
 
     datalen = len(gdsdata)
-    if debug:
+    if debug > 0:
         print('Original data length = ' + str(datalen))
     dataptr = 0
     while dataptr < datalen:
@@ -83,40 +104,53 @@
         if rectype in recordfilter:
             # Datatype 6 is STRING
             if datatype == 6:
-                if debug:
-                    print('Record type = ' + str(rectype) + ' data type = ' + str(datatype) + ' length = ' + str(reclen))
-
                 bstring = gdsdata[dataptr + 4: dataptr + reclen]
-                repstring = bstring.replace(bsearch, brep)
-                if repstring != bstring:
-                    before = gdsdata[0:dataptr]
-                    after = gdsdata[dataptr + reclen:]
-                    newlen = len(repstring) + 4
-                    # Record sizes must be even
-                    if newlen % 2 != 0:
-                        # Was original string padded with null byte?  If so,
-                        # remove the null byte and reduce newlen.  Otherwise,
-                        # add a null byte and increase newlen.
+                if debug > 1:
+                    idx = recordfilter.index(rectype)
+                    print(recordtypes[idx] + ' string = ' + str(bstring))
+
+                for bsearch,brep in zip(bsearchlist, breplist):
+                    # Verbatim option:  search string must match GDS string exactly
+                    if verbatim:
+                        blen = reclen - 4
                         if bstring[-1] == 0:
-                            repstring = repstring[0:-1]
-                            newlen -= 1
-                        else:
-                            repstring += b'\x00'
-                            newlen += 1
+                            blen = blen - 1
+                        if len(bsearch) != blen:
+                            continue
+                    repstring = re.sub(bsearch, brep, bstring)
+                    if repstring != bstring:
+                        before = gdsdata[0:dataptr]
+                        after = gdsdata[dataptr + reclen:]
+                        newlen = len(repstring) + 4
+                        # Record sizes must be even
+                        if newlen % 2 != 0:
+                            # Was original string padded with null byte?  If so,
+                            # remove the null byte and reduce newlen.  Otherwise,
+                            # add a null byte and increase newlen.
+                            if bstring[-1] == 0:
+                                repstring = repstring[0:-1]
+                                newlen -= 1
+                            else:
+                                repstring += b'\x00'
+                                newlen += 1
                             
-                    bnewlen = newlen.to_bytes(2, byteorder='big')
-                    brectype = rectype.to_bytes(1, byteorder='big')
-                    bdatatype = datatype.to_bytes(1, byteorder='big')
+                        bnewlen = newlen.to_bytes(2, byteorder='big')
+                        brectype = rectype.to_bytes(1, byteorder='big')
+                        bdatatype = datatype.to_bytes(1, byteorder='big')
 
-                    # Assemble the new record
-                    newrecord = bnewlen + brectype + bdatatype + repstring
-                    # Reassemble the GDS data around the new record
-                    gdsdata = before + newrecord[0:newlen] + after
-                    # Adjust the data end location
-                    datalen += (newlen - reclen)
+                        # Assemble the new record
+                        newrecord = bnewlen + brectype + bdatatype + repstring
+                        # Reassemble the GDS data around the new record
+                        gdsdata = before + newrecord[0:newlen] + after
+                        # Adjust the data end location
+                        datalen += (newlen - reclen)
 
-                    if debug:
-                        print('Replaced ' + str(bstring) + ' with ' + str(repstring)) 
+                        if debug > 0:
+                            print('Replaced ' + str(bstring) + ' with ' + str(repstring)) 
+            else:
+                if debug > 1:
+                    idx = recordfilter.index(rectype)
+                    print(recordtypes[idx] + ' record = ' + str(datatype) + ' is not a string')
 
         # Advance the pointer past the data
         dataptr += newlen
diff --git a/common/find_gds_prefix.py b/common/find_gds_prefix.py
index aeab8cc..e8dba84 100755
--- a/common/find_gds_prefix.py
+++ b/common/find_gds_prefix.py
@@ -84,7 +84,7 @@
             strname = bstring.decode('ascii')
             if strname[3:] == cellname:
                 print('Cell ' + strname + ' found at position ' + str(saveptr))
-                print('Prefix: ' + strname[0:2])
+                print('Prefix: ' + strname[0:3])
                 found = True
                 break
             elif strname == cellname: