/ scripts / update_ini
update_ini
  1  #!/usr/bin/env python
  2  
  3  THIS_VERSION = "1.1"
  4  
  5  import sys
  6  import os
  7  import shutil
  8  import linuxcnc
  9  import re
 10  import datetime
 11  from Tkinter import *
 12  import tkMessageBox
 13  
 14  def copysection(block):
 15      #Just makes a straight copy of blocks that don't need any work
 16      regex = "^\s*\[%s\](.+?)(?:^\s*\[|\Z)" % block
 17      section = re.search(regex, inistring, re.M | re.DOTALL)
 18      newini.write("\n[%s]" % block)
 19      if section != None:
 20          newini.write(section.group(1))
 21          all_sections.remove(block)
 22      else:
 23           newini.write("\n#No Content\n")
 24  
 25  def writeifexists(file, section, src_item, dest_item = "None"):
 26      #Writes a new entry to the file, but only if it exists
 27      if dest_item == 'None': dest_item = src_item
 28      val = ini.find(section, src_item)
 29      if val: file.write("%s = %s\n" % (dest_item, val))
 30  
 31  force = 0
 32  dialogs = 0
 33  subs = {}
 34  subs2 = {}
 35  
 36  filename = None
 37  for opt in sys.argv[1:]:
 38      if opt == '-d':
 39          dialogs = 1
 40          r = Tk()
 41          r.option_add('*Dialog.msg.font', 'Times 12')
 42          r.option_add('*Dialog.msg.wrapLength', '6i')
 43  
 44      elif opt == '-f':
 45          force = 1
 46      elif opt[0] == '-':
 47          print "Unknown command line option to update_ini, exiting"
 48          exit()
 49      elif os.path.isfile(opt):
 50          filename = opt
 51  
 52  if filename == None:
 53      t = """Usage: update_ini [-d] [-f] filename.ini\n
 54  If the -d flag is used then a dialog box will be displayed
 55  describing the purpose of this script, and giving the user the option
 56  to change their minds\nIf the -f flag is used then no questions will be
 57  asked and the conversion will proceed blindly"""
 58      if dialogs:
 59          tkMessageBox.showerror('invalid options', str(t))
 60      elif not force:
 61          print t
 62      exit()
 63  
 64  if dialogs:
 65      ret = tkMessageBox._show("Confirm automatic update",
 66                             "This version of LinuxCNC separates the concepts of Axes and "
 67                             "Joints which necessitates changes to the INI and HAL files. "
 68                             "The changes required are described here:\n"
 69                             "http://linuxcnc.org/docs/devel/html/ in the section "
 70                             "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n"
 71                             "The [EMC]VERSION data in your INI file indicates that your "
 72                             "configuration requires update.\n"
 73                             "A script exists that can attempt to automatically "
 74                             "reconfigure your configuration files.\nPress 'Yes' to perform "
 75                             "the conversion, 'No' to continue with the current configuration "
 76                             "files or 'Cancel' to exit LinuxCNC.\n"
 77                             "The process can not be automatically reversed, though a "
 78                             "backup version of your entire existing config will be created.",
 79                             tkMessageBox.QUESTION, tkMessageBox.YESNOCANCEL)
 80      if ret == 'cancel': exit(42)
 81      elif ret == 'no': exit(0)
 82  
 83  # We want to work with the base INI file here, not the expanded version if #include is used
 84  filename = re.sub(r'\.expanded', '', filename)
 85  
 86  try:
 87      ini = linuxcnc.ini(filename)
 88  except:
 89      t =  "%s is not a valid ini file" % filename
 90      if dialogs:
 91          tkMessageBox.showerror('invalid options', t)
 92      elif not force:
 93          print t
 94      exit()
 95  
 96  version = ini.find('EMC', 'VERSION')
 97  if not version:
 98      version = "0.0"
 99  
100  if version == "$Revision$":
101      pass
102  elif version >= THIS_VERSION:
103      t =  """The supplied INI file is already at version %s and should not need
104      updating""" % version
105      if dialogs:
106          tkMessageBox.showerror('conversion not needed', t)
107      elif not force:
108          print t
109      exit()
110  
111  if ini.find('KINS', 'JOINTS') and not force and not version == "1.0":
112      if dialogs:
113          if tkMessageBox.askquestion("Already Converted",
114          "The supplied INI file already has a [KINS] section. this probably "
115          "means that it was previously converted by hand. Continue conversion?"
116          "(Change [EMC]VERSION to %s to suppress these messages) "
117          % THIS_VERSION) != 'yes':
118              exit(0)
119      else:
120          if raw_input("The supplied INI file already has a [KINS] section."
121          "this probably means that it was previously converted by hand. "
122          "Continue y/N? (Change [EMC]VERSION to %s to suppress these messages) "
123          % THIS_VERSION) != "y":
124              exit(0)
125  
126  # Looks like we are good to go, so first let's put the original configs
127  # somewhere safe.
128  
129  basedir = os.path.dirname(os.path.abspath(filename))
130  backupdir = os.path.join(basedir, os.path.splitext(os.path.basename(filename))[0] + ".old")
131  
132  while os.path.isdir(backupdir):
133      backupdir += ".old"
134  os.mkdir(backupdir)
135  old_ini =  os.path.join(backupdir, os.path.basename(filename))
136  for f in os.listdir(basedir):
137      if os.path.isdir(os.path.join(basedir, os.path.basename(f))):
138          pass
139      else:
140          shutil.copy(os.path.join(basedir, os.path.basename(f)), 
141                      os.path.join(backupdir, os.path.basename(f)))
142  
143  #From now on, we use the backup copy as the reference
144  ini = linuxcnc.ini(old_ini)
145  
146  #And the hal files too.
147  halfiles = ini.findall('HAL', 'HALFILE')
148  halfiles += ini.findall('HAL', 'POSTGUI_HALFILE')
149  halfiles += ['touchy.hal']
150  print "halfiles = ", halfiles
151  
152  halpaths = []
153  for halfile in halfiles:
154      if os.path.isfile(os.path.join(basedir, halfile)):
155          halpaths.append(os.path.join(basedir, halfile))
156      elif (os.path.isfile(os.path.join(basedir, "hallib", halfile))):
157          os.system('cp ' + os.path.join(basedir, "hallib", halfile) + ' ' +
158                     os.path.join(basedir, halfile))
159          halpaths.append(os.path.join(basedir, halfile))
160      elif halfile == "touchy.hal":
161          pass
162      else:
163          print "halfile %s not found\n" % halfile
164  
165  print "halpaths = ", halpaths
166  
167  if version == "1.0":
168      #Just update the version in the INI
169      inistring = open(filename,'r').read()
170      newini = open(filename, 'w')
171      inistring = re.sub("VERSION *= *(.*)", "VERSION = %s" % THIS_VERSION, inistring)
172      newini.write(inistring)
173      newini.close()
174  
175  if version == "$Revision$" or version < "1.0":
176      
177      inistring = open(filename,'r').read()
178      newini = open(filename, 'w')
179      # Get a list of all sections
180      all_sections = re.findall("^\s*\[(.+)\]", inistring, re.MULTILINE)
181  
182      # A C-style Switch would be nice here, to allow us to fall through successive
183      # version updates.
184      # At the moment there is only one update, but any future updates should be
185      # a second "if version == 1.0" and so on. The first "if" needs to change the
186      # version string, though.
187  
188      newini.write("# This config file was created %s by the update_ini script\n" % datetime.datetime.now())
189      newini.write("# The original config files may be found in the %s directory\n\n" % backupdir)
190  
191      # reproduce everything before the first [section] verbatim
192      section = re.match("(.*?)^\[", inistring, re.DOTALL | re.MULTILINE)
193      if section !=None:
194          newini.write(section.group(1))
195  
196      #[EMC] Section, change the version number
197      all_sections.remove("EMC")
198      section = re.search("\[EMC\](.+?)\n\[", inistring, re.DOTALL)
199      if section: section = section.group(1)
200      newini.write("[EMC]\n")
201      if section != None:
202          if version != "0.0":
203              section = re.sub("VERSION (.+)", "VERSION = %s" % THIS_VERSION, section)
204          else:
205              newini.write("# The version string for this INI file.\n")
206              newini.write("VERSION = %s\n" % THIS_VERSION)
207          newini.write(section)
208      else:
209           newini.write("VERSION = %s\n" % THIS_VERSION)
210  
211      #These sections don't need any work.
212      copysection("DISPLAY")
213      copysection("FILTER")
214      copysection("RS274NGC")
215  
216      all_sections.remove("EMCMOT")
217      section = re.search("\[EMCMOT\](.+?)\n\[", inistring, re.DOTALL)
218      if section: section = section.group(1)
219      newini.write("[EMCMOT]\n")
220      section = re.sub("# Interval between tries to emcmot.*?\n", "", section)
221      section = re.sub("COMM_WAIT.*?\n", "", section)
222      newini.write(section)
223  
224      copysection("TASK")
225      copysection("HAL")
226      copysection("HALUI")
227  
228      # We need info from TRAJ to get KINS right
229  
230      joints = ini.find("TRAJ", "JOINTS")
231      coordinates = ini.find("TRAJ", "COORDINATES").replace(" ","")
232      if coordinates != None: joints = len(coordinates)
233      if joints == None: joints = ini.find("TRAJ", "AXES")
234      if joints == None: joints = "3"
235      joints = int(joints)
236      if coordinates == None: coordinates = "XYZABCUVW"
237  
238      coordinates = list(coordinates)
239  
240      # Search the Halfiles to find the kinematics.
241      kins = None
242      kinstype = None
243      coords_entry = False
244      if coordinates != "XYZABCUVW"[:joints]: coords_entry = True
245      for halfile in halpaths:
246          hal = open(os.path.join(os.path.dirname(filename), halfile), 'r')
247          for line in hal.readlines():
248              match = re.match('(?:#autoconverted|loadrt) +(\w+kins)', line)
249              if match:
250                  kins = match.group(1)
251                  match = re.search('coordinates *= *(\w+)', line)
252                  if match:
253                      coordinates = list(match.group(1))
254                      coords_entry = 1
255                  match = re.search('kinstype *= *(\w+)', line)
256                  if kinstype: kinstype = match.group(1)
257                  break
258          if kins: break
259      if not kins: kins = "trivkins"
260  
261      #gantrykins and gentrivkins are gone, so need special treatment
262  
263      if  kins == "gantrykins":
264          kins = "trivkins"
265          kinstype = "BOTH"
266          coords_entry = True
267          for halfile in halpaths:
268              hal = open(os.path.join(os.path.dirname(filename), halfile), 'r')
269              for line in hal.readlines():
270                  match = re.match('setp +gantrykins.joint-(\d) +(\d)', line)
271                  if match:
272                      j = int(match.group(1))
273                      if j > joints: joints = j
274                      a = int(match.group(2))
275                      coordinates[j] = 'XYZABCUVW'[a]
276  
277      if kins == "gentrivkins":
278          kins = "trivkins" #trivkins has the same defaults as gentrivkins
279  
280      # In JA [TRAJ] expects MAX_LINEAR_VELOCITY not MAX_VELOCITY
281      all_sections.remove("TRAJ")
282      section = re.search("\[TRAJ\](.+?)\n\[", inistring, re.DOTALL)
283      if section: section = section.group(1)
284      newini.write("\n[TRAJ]\n")
285      if section != None:
286          if not re.search("MAX_LINEAR_VELOCITY", section):
287              if re.search("MAX_VELOCITY", section):
288                  section = re.sub("MAX_VELOCITY", "MAX_LINEAR_VELOCITY", section)
289              else:
290                  mv = re.findall("MAX_VELOCITY[\s=]+(\d*(\.\d+)?)", inistring, re.MULTILINE)
291                  section = ("\n# this value based on fastest single axis" +
292                            "\nMAX_LINEAR_VELOCITY = %s" % max(mv)[0] + section)
293          if not re.search("DEFAULT_LINEAR_VELOCITY", section):
294              section = re.sub("DEFAULT_VELOCITY", "DEFAULT_LINEAR_VELOCITY", section)
295          if not re.search("MAX_LINEAR_ACCELERATION", section):
296              section = re.sub("MAX_ACCELERATION", "MAX_LINEAR_ACCELERATION", section)
297          if not re.search("DEFAULT_ACCELERATION", section):
298              section = re.sub("DEFAULT_ACCELERATION", "DEFAULT_LINEAR_ACCELERATION", section)
299          print "COORDINATES = %s\n" % ''.join(coordinates)
300          section = re.sub("COORDINATES.*", "COORDINATES = %s" % ''.join(coordinates[: joints]), section)
301          section = re.sub("CYCLE_TIME.*?\n", "", section)
302          section = re.sub("AXES *=.*\n", "", section)
303          newini.write(section)
304  
305      copysection("EMCIO")
306  
307      # Insert the new-fangled [KINS] section
308  
309      newini.write("\n\n[KINS]\n")
310      newini.write("KINEMATICS = %s" % kins)
311      if coords_entry: newini.write(" coordinates=%s" % ''.join(coordinates[: joints]))
312      if kinstype: newini.write(" kinstype=%s" % kinstype)
313      newini.write("\n")
314      newini.write("#This is a best-guess at the number of joints, it should be checked\n")
315      newini.write("JOINTS = %i\n" % joints)
316  
317      j = 0
318      lock_mask = 0x0
319      L2J={}
320      while 1:
321           # Search preferentially in "[JOINT_N] in case the file is part-converted already
322          if re.search("^(\[JOINT_%i\])"%j, inistring, re.MULTILINE):
323              if re.search("^(\[AXIS_%s\])" % "XYZABCUVW"[j], inistring, re.MULTILINE):
324                  copysection("AXIS_%s" % "XYZABCUVW"[j])
325              #    copysection("JOINT_%i" % j)
326              elif j < len(coordinates):
327                  newini.write("\n[AXIS_%s]\n" % coordinates[j])
328                  writeifexists(newini, "JOINT_%i" % j, "HOME")
329                  writeifexists(newini, "JOINT_%i" % j, "MIN_LIMIT")
330                  writeifexists(newini, "JOINT_%i" % j, "MAX_LIMIT")
331                  writeifexists(newini, "JOINT_%i" % j, "MAX_VELOCITY")
332                  writeifexists(newini, "JOINT_%i" % j, "MAX_ACCELERATION")
333                  copysection("[JOINT_%i]" % j)
334          elif j < len(coordinates):
335              # in this "elif" j is an index in to coordinates. 
336              if coordinates[j] in L2J: # duplicate axis letter
337                  L2J[coordinates[j]].append(j) # = [L2J[coordinates[j]], j]
338              else:
339                  L2J.update({coordinates[j] : [j]})
340          elif j >= 9:
341              break
342          else:
343              pass
344  
345          j += 1
346  
347      for L in list("XYZABCUVW"):
348          if L in L2J:
349              axisnum = "XYZABCUVW".index(L)
350              newini.write("\n[AXIS_%s]\n" % L)
351              writeifexists(newini, "AXIS_%i" % axisnum, "MIN_LIMIT")
352              writeifexists(newini, "AXIS_%i" % axisnum, "MAX_LIMIT")
353              writeifexists(newini, "AXIS_%i" % axisnum, "MAX_VELOCITY")
354              writeifexists(newini, "AXIS_%i" % axisnum, "MAX_ACCELERATION")
355              if ini.find("AXIS_%i" % j, "LOCKING_INDEXER"):
356                  lock_mask |= 1 << j
357                  newini.write("LOCKING_INDEXER_JOINT = %i\n" % j)
358                  
359              hs = ini.find("AXIS_%i" % axisnum, "HOME_SEQUENCE")
360              if hs == "-1" or hs == None: # -1 used to exclude a joint now we use no entry
361                  sequence = ""
362              elif len(L2J[L]) > 1:  # tandem axis
363                  sequence = "HOME_SEQUENCE = -%s" % hs
364              else:
365                  sequence = "HOME_SEQUENCE = %s" % hs
366              for J in L2J[L]:
367                  # Take the coordinates index as the JOINT_Number
368                  newini.write("\n[JOINT_%i]" % J)
369                  section = re.search("\[AXIS_%i\](.+?)(\n\[|$)" % J, inistring, re.DOTALL)
370                  if not section:
371                      section = re.search("\[AXIS_%i\](.+?)(\n\[|$)" % "XYZABCUVW".index(coordinates[J]), inistring, re.DOTALL)
372                  if section:
373                      section = re.sub("HOME_SEQUENCE.*", sequence, section.group(1))
374                      newini.write(section)
375                      if not '\[AXIS_%i\]' % axisnum in subs:
376                          subs.update({'\[AXIS_%i\]' % axisnum : '[JOINT_%i]' % J})
377                          subs2.update({'joint\.%i\.' % axisnum : 'joint.%i.' % J})
378                      else:
379                          subs.update({'\[AXIS_%i\]' % J : '[JOINT_%i]' % J})
380                  else:
381                      print "File parsing error, found an [AXIS_%i] section, but no content" % J
382                      exit()
383      # We no longer need the [AXIS_N] data
384      for j in range(0,8):
385           if ("AXIS_%i" % j) in all_sections: all_sections.remove("AXIS_%i" % j)
386  
387      # If there were any custom sections, tag them on the end.
388      while all_sections:
389          copysection(all_sections[0])
390  
391      # and turn the locking mask into a string
392      if lock_mask:
393          lock_string = 'unlock_joints_mask=%i' % lock_mask
394      else:
395          lock_string = ""
396  
397      #That's the INI file done:
398      newini.close()
399  
400  
401  
402      # Now change all the pin names etc in the linked HAL files.
403      # Any machine can be jogged in world mode (in theory) but joint-mode jog-enable
404      # is not auto-linked for safety.
405  
406  if version == "$Revision$" or version < "1.0":
407      
408      subs.update({'axis.(.).active':'joint.\\1.active',
409      'axis.(.).amp-enable-out':    'joint.\\1.amp-enable-out',
410      'axis.(.).amp-fault-in':      'joint.\\1.amp-fault-in',
411      'axis.(.).backlash-corr':     'joint.\\1.backlash-corr',
412      'axis.(.).backlash-filt':     'joint.\\1.backlash-filt',
413      'axis.(.).backlash-vel':      'joint.\\1.backlash-vel',
414      'axis.(.).coarse-pos-cmd':    'joint.\\1.coarse-pos-cmd',
415      'axis.(.).error':             'joint.\\1.error',
416      'axis.(.).f-error':           'joint.\\1.f-error',
417      'axis.(.).f-error-lim':       'joint.\\1.f-error-lim',
418      'axis.(.).f-errored':         'joint.\\1.f-errored',
419      'axis.(.).faulted':           'joint.\\1.faulted',
420      'axis.(.).free-pos-cmd':      'joint.\\1.free-pos-cmd',
421      'axis.(.).free-tp-enable':    'joint.\\1.free-tp-enable',
422      'axis.(.).free-vel-lim':      'joint.\\1.free-vel-lim',
423      'axis.(.).home-state':        'joint.\\1.home-state',
424      'axis.(.).home-sw-in':        'joint.\\1.home-sw-in',
425      'axis.(.).homed':             'joint.\\1.homed',
426      'axis.(.).homing':            'joint.\\1.homing',
427      'axis.(.).in-position':       'joint.\\1.in-position',
428      'axis.(.).index-enable':      'joint.\\1.index-enable',
429      'axis.(.).joint-pos-cmd':     'joint.\\1.pos-cmd',
430      'axis.(.).joint-pos-fb':      'joint.\\1.pos-fb',
431      'axis.(.).joint-vel-cmd':     'joint.\\1.vel-cmd',
432      'axis.(.).kb-jog-active':     'joint.\\1.kb-jog-active',
433      'axis.(.).motor-offset':      'joint.\\1.motor-offset',
434      'axis.(.).motor-pos-cmd':     'joint.\\1.motor-pos-cmd',
435      'axis.(.).motor-pos-fb':      'joint.\\1.motor-pos-fb',
436      'axis.(.).neg-hard-limit':    'joint.\\1.neg-hard-limit',
437      'axis.(.).neg-lim-sw-in':     'joint.\\1.neg-lim-sw-in',
438      'axis.(.).pos-hard-limit':    'joint.\\1.pos-hard-limit',
439      'axis.(.).pos-lim-sw-in':     'joint.\\1.pos-lim-sw-in',
440      'axis.(.).wheel-jog-active':  'joint.\\1.wheel-jog-active',
441      'axis.(.).unlock':            'joint.\\1.unlock',
442      'axis.(.).is-unlocked':       'joint.\\1.is-unlocked',
443      'axis.(.).jog-enable':        '@ax\\1@.jog-enable',
444      'axis.(.).jog-counts':        'joint.\\1.jog-counts @ax\\1@.jog-counts',
445      'axis.(.).jog-scale':         'joint.\\1.jog-scale @ax\\1@.jog-scale',
446      'axis.(.).jog-vel-mode':      'joint.\\1.jog-vel-mode @ax\\1@.jog-vel-mode',
447      'halui.axis.(.).pos-commanded':'halui.@ax\\1@.pos-commanded',
448      'halui.axis.(.).pos-feedback':'halui.@ax\\1@.pos-feedback',
449      'halui.axis.(.).pos-relative':'halui.@ax\\1@.pos-relative',
450      'halui.joint.(.).is-selected':'halui.@ax\\1@.is-selected',
451      'halui.jog.(.).analog':       'halui.@ax\\1@.analog',
452      'halui.jog.(.).increment':    'halui.@ax\\1@.increment',
453      'halui.jog.(.).increment-minus':'halui.@ax\\1@.increment-minus',
454      'halui.jog.(.).increment-plus':'halui.@ax\\1@.increment-plus',
455      'halui.jog.(.).minus':        'halui.@ax\\1@.minus',
456      'halui.jog.(.).plus':         'halui.@ax\\1@.plus',
457      'halui.joint.(.).select':     'halui.@ax\\1@.select',
458      'halui.jog.selected.increment':'halui.axis.selected.increment',
459      'halui.jog.selected.increment-minus':'halui.axis.selected.increment-minus',
460      'halui.jog.selected.increment-plus':'halui.axis.selected.increment-plus',
461      'halui.jog.selected.minus':   'halui.axis.selected.minus',
462      'halui.jog.selected.plus':    'halui.axis.selected.plus',
463      'halui.jog-deadband':         'halui.axis.jog-deadband',
464      'halui.jog-speed':            'halui.axis.jog-speed',
465      'halui.joint.selected':       'halui.joint.selected',
466      'halui.joint.selected.is_homed':'halui.joint.selected.is-homed',
467      'halui.joint.selected.on-soft-limit':'halui.joint.selected.on-soft-max-limit',
468      'num_joints=\[TRAJ\]AXES':    'num_joints=[KINS]JOINTS',
469      'loadrt(.+kins)':             'loadrt [KINS]KINEMATICS\n#autoconverted \\1',
470  
471      '(setp +gantrykins.+)':       '# \\1',
472      '(.+servo_period_ns.+)':      '\\1 %s' % lock_string
473      })
474  
475      # converts @axN@ pattern to axis.L and splits any malformed setp from mpg
476      subs2.update({
477      '^\s*setp\s+(joint\S+)\s+(axis\S+)\s+(\S+)\s*$':
478                                   'setp \\1 \\3\nsetp \\2 \\3\n',
479      '@ax0@':                     'axis.x',
480      '@ax1@':                     'axis.y',
481      '@ax2@':                     'axis.z',
482      '@ax3@':                     'axis.a',
483      '@ax4@':                     'axis.b',
484      '@ax5@':                     'axis.c',
485      '@ax6@':                     'axis.u',
486      '@ax7@':                     'axis.v',
487      '@ax8@':                     'axis.w',
488      })
489      
490  if version < "1.1":
491      subs.update({
492          'motion.spindle-brake'                  : 'spindle.0.brake',
493          'motion.spindle-forward'                : 'spindle.0.forward',
494          'motion.spindle-index-enable'           : 'spindle.0.index-enable',
495          'motion.spindle-inhibit'                : 'spindle.0.inhibit',
496          'motion.spindle-on'                     : 'spindle.0.on',
497          'motion.spindle-reverse'                : 'spindle.0.reverse',
498          'motion.spindle-revs'                   : 'spindle.0.revs',
499          'motion.spindle-speed-in'               : 'spindle.0.speed-in',
500          'motion.spindle-speed-out'              : 'spindle.0.speed-out',
501          'motion.spindle-speed-out-abs'          : 'spindle.0.speed-out-abs',
502          'motion.spindle-speed-out-rps'          : 'spindle.0.speed-out-rps',
503          'motion.spindle-speed-out-rps-abs'      : 'spindle.0.speed-out-rps-abs',
504          'motion.spindle-orient-angle'           : 'spindle.0.orient-angle', 
505          'motion.spindle-orient-mode'            : 'spindle.0.orient-mode',
506          'motion.spindle-orient'                 : 'spindle.0.orient',
507          'motion.spindle-is-oriented'            : 'spindle.0.is-oriented',
508          'motion.spindle-orient-fault'           : 'spindle.0.orient-fault',
509          'motion.spindle-locked'                 : 'spindle.0.locked',
510          'motion.spindle-at-speed'               : 'spindle.0.at-speed',
511          'halui.spindle.brake-is-on'             : 'halui.spindle.0.brake-is-on',
512          'halui.spindle.brake-off'               : 'halui.spindle.0.brake-off',
513          'halui.spindle.brake-on'                : 'halui.spindle.0.brake-on',
514          'halui.spindle.decrease'                : 'halui.spindle.0.decrease',
515          'halui.spindle.forward'                 : 'halui.spindle.0.forward',
516          'halui.spindle.increase'                : 'halui.spindle.0.increase',
517          'halui.spindle.is-on'                   : 'halui.spindle.0.is-on',
518          'halui.spindle.reverse'                 : 'halui.spindle.0.reverse',
519          'halui.spindle.runs-backward'           : 'halui.spindle.0.runs-backward',
520          'halui.spindle.runs-forward'            : 'halui.spindle.0.runs-forward',
521          'halui.spindle.start'                   : 'halui.spindle.0.start',
522          'halui.spindle.stop'                    : 'halui.spindle.0.stop',
523          'halui.spindle.override.count-enable'   : 'halui.spindle.0.override.count-enable',
524          'halui.spindle.override.counts'         : 'halui.spindle.0.override.counts',
525          'halui.spindle.override.decrease'       : 'halui.spindle.0.override.decrease',
526          'halui.spindle.override.direct-value'   : 'halui.spindle.0.override.direct-value',
527          'halui.spindle.override.increase'       : 'halui.spindle.0.override.increase',
528          'halui.spindle.override.scale'          : 'halui.spindle.0.override.scale',
529          'halui.spindle.override.value'          : 'halui.spindle.0.override.value'
530          })
531  
532  if subs == {}:
533      print """This file does not need converting, and furthermore execution
534      should never have reached this spot"""
535  else:
536      for halfile in halpaths:
537          halstring = open(halfile,'r').read()
538          for sub in subs:
539              halstring = re.sub(sub, subs[sub], halstring, flags=re.M)
540          for sub in subs2:
541              halstring = re.sub(sub, subs2[sub], halstring, flags=re.M)
542          newhal = open(halfile, 'w')
543          newhal.write(halstring)
544          newhal.close()
545  
546  if force:
547      shutil.rmtree(backupdir)