fixed paths for GENERATED
[coreboot.git] / util / newconfig / config.g
1 import sys
2 import os
3 import re
4 import string
5
6 debug = 0
7 warnings = 0
8 errors = 0
9
10 arch = ''
11 ldscriptbase = ''
12 payloadfile = ''
13
14 makeoptions = {}
15 makeexpressions = []
16
17 # Key is the rule name. Value is a mkrule object.
18 makebaserules = {}
19
20 # List of targets in the order defined by makerule commands.
21 makerule_targets = {}
22
23 treetop = ''
24 target_dir = ''
25
26 sources = {}
27 objectrules = {}
28 # make these a hash so they will be unique.
29 driverrules = {}
30 ldscripts = []
31 userdefines = []
32 curpart = 0
33 root = 0
34
35 globalvars = {}       # We will globals here
36 parts = {}
37
38 options = {}
39 # options in order defined. These will be unique due to use of hash 
40 # for options. 
41 options_by_order = []
42 crt0includes = []
43 partinstance = 0
44 curdir = '' 
45 dirstack = []
46 config_file_list = []
47
48 local_path = re.compile(r'^\.')
49
50 # -----------------------------------------------------------------------------
51 #                    Error Handling
52 # -----------------------------------------------------------------------------
53
54 class location:
55         class place:
56                 def __init__(self, file, line, command):
57                         self.file = file
58                         self.line = line
59                         self.command = command
60                 def next_line(self, command):
61                         self.line = self.line + 1
62                         self.command = command
63                 def at(self):
64                         return "%s:%d" % (self.file, self.line)
65         
66         def __init__ (self):
67                 self.stack = []
68
69         def file(self):
70                 return self.stack[-1].file
71         def line(self):
72                  return self.stack[-1].line
73         def command(self):
74                 return self.stack[-1].command
75
76         def push_file(self, file):
77                 self.stack.append(self.place(file, 0, ""))
78         def pop_file(self):
79                 self.stack.pop()
80         def next_line(self, command):
81                 self.stack[-1].next_line(command)
82         def at(self):
83                 return self.stack[-1].at()
84 loc = location()
85
86 class makerule:
87         def __init__ (self, target):
88                 self.target = target
89                 self.dependency = []
90                 self.actions = []
91
92         def addaction(self, action):
93                 self.actions.append(action)
94
95         def adddependency(self, dependency):
96                 self.dependency.append(dependency)
97
98         def gtarget(self):
99                 return self.target
100
101         def gdependency(self):
102                 return self.dependency
103
104         def gaction(self):
105                 return self.actions
106
107 class option:
108         def __init__ (self, name):
109                 self.name = name        # name of option
110                 self.loc = 0            # current location
111                 self.value = 0          # option value
112                 self.set = 0            # option has been set
113                 self.used = 0           # option has been set
114                 self.default = 0        # option has default value (otherwise
115                                         # it is undefined)
116                 self.comment = ''       # description of option
117                 self.exportable = 0     # option is able to be exported
118                 self.exported = 0       # option is exported
119                 self.defined = 0        # option has a value
120                 self.format = '%s'      # option print format
121
122         def setvalue(self, value, loc):
123                 if (self.set):
124                         print "Option %s: " % self.name
125                         print "Attempt to set %s at %s" % (value, loc.at()) 
126                         print "Already set to %s at %s" % \
127                                         (self.value, self.loc.at())
128                         sys.exit(1)
129                 self.set = 1
130                 self.value = value
131                 self.defined = 1
132                 self.loc = loc
133
134         def getvalue(self, part):
135                 global curpart
136                 if (not (type(self.value) is str)):
137                         return self.value
138                 if (self.value == '' or self.value[0] != '{'):
139                         return self.value
140                 # save curpart so we can evaluate expression
141                 # in context of part
142                 s = curpart
143                 curpart = part
144                 v = parse('delexpr', self.value)
145                 # TODO: need to check for parse errors!
146                 curpart = s
147                 return v
148
149         def setdefault(self, value, loc):
150                 if (self.default):
151                         print "%s: " % self.name
152                         print "Attempt to default %s at %s" % (value, loc) 
153                         print "Already defaulted to %s at %s" %  \
154                                         (self.value, self.loc.at())
155                         print "Warning only"
156                 if (self.set):
157                         print "%s: " % self.name
158                         print "Attempt to default %s at %s" % (value, loc) 
159                         print "Already set to %s at %s" % \
160                                         (self.value, self.loc.at())
161                         print "Warning only"
162                         return
163                 self.value = value
164                 self.defined = 1
165                 self.default = 1
166                 self.loc = loc
167
168         def setnodefault(self, loc):
169                 self.default = 1
170                 self.defined = 0
171                 self.loc = loc
172
173         def where(self):
174                 return self.loc
175
176         def setcomment(self, value, loc):
177                 if (self.comment != ''):
178                         print "%s: " % self.name
179                         print "Attempt to modify comment at %s" % loc 
180                         return
181                 self.comment = value
182
183         def setexportable(self):
184                 self.exportable = 1
185
186         def setexported(self):
187                 self.exportable = 1
188                 self.exported = 1
189
190         def setnoexport(self):
191                 self.exportable = 0
192                 self.exported = 0
193
194         def setformat(self, fmt):
195                 self.format = fmt
196
197         def getformat(self):
198                 return self.format
199
200         def setused(self):
201                 if (self.exportable):
202                         self.exported = 1
203                 self.used = 1
204
205         def isexported(self):
206                 return (self.exported and self.defined)
207
208         def isdefined(self):
209                 return (self.defined)
210
211         def isset(self):
212                 return (self.set)
213
214         def isused(self):
215                 return (self.used)
216
217 class partobj:
218         def __init__ (self, dir, parent, type):
219                 global partinstance
220                 if (debug):
221                         print "partobj dir %s parent %s type %s" %(dir,parent,type)
222                 self.children = []
223                 self.initcode = []
224                 self.registercode = []
225                 self.siblings = 0
226                 self.type = type
227                 self.objects = []
228                 self.dir = dir
229                 self.irq = 0
230                 self.instance = partinstance + 1
231                 partinstance = partinstance + 1
232                 self.devfn = 0  
233                 self.private = 0        
234                 self.options = {}
235                 if (parent):
236                         if (debug):
237                                 print "add to parent"
238                         self.parent   = parent
239                         parent.children.append(self)
240                 else:
241                         self.parent = self
242
243         def dumpme(self, lvl):
244                 print "%d: type %s" % (lvl, self.type)
245                 print "%d: dir %s" % (lvl,self.dir)
246                 print "%d: parent %s" % (lvl,self.parent.type)
247                 print "%d: parent dir %s" % (lvl,self.parent.dir)
248                 print "%d: initcode " % lvl
249                 for i in self.initcode:
250                         print "  %s" % i
251                 print "%d: registercode " % lvl
252                 for i in self.registercode:
253                         print "  %s" % i
254
255         def gencode(self):
256                 print "struct cdev dev%d = {" % self.instance
257                 print "/* %s %s */" % (self.type, self.dir)
258                 print "  .devfn = %d" % self.devfn
259                 if (self.siblings):
260                         print "  .next = &dev%d" % self.sibling.instance
261                 if (self.children):
262                         print "  .children = &dev%d" %  \
263                                         self.children[0].instance
264                 if (self.private):
265                         print "  .private = private%d" % self.instance
266                 print "};"
267
268                 
269         def irq(self, irq):
270                 self.irq = irq
271        
272         def addinit(self, code):
273                 self.initcode.append(code)
274                 
275         def addregister(self, code):
276                 self.registercode.append(code)
277
278         def usesoption(self, name):
279                 o = getvalue(options, name)
280                 if (o == 0):
281                         fatal("Error: can't use undefined option %s" % name)
282                 o.setused()
283                 setvalue(self.options, name, o)
284                 if (debug):
285                         print "option %s used in %s" % (name, self)
286
287 class partsstack:
288         def __init__ (self):
289                 self.stack = []
290
291         def push(self, part):
292                 self.stack.append(part)
293
294         def pop(self):
295                 return self.stack.pop()
296
297         def tos(self):
298                 return self.stack[-1]
299 pstack = partsstack()
300
301 def error(string):      
302         global errors, loc
303         errors = errors + 1
304         size = len(loc.stack)
305         i = 0
306         while(i < size -1): 
307                 print loc.stack[i].at()
308                 i = i + 1
309         print "%s: %s"% (loc.at(), string)
310
311 def exitiferrors():
312         if (errors != 0):
313                 sys.exit(1)
314
315 def fatal(string):      
316         error(string)
317         exitiferrors()
318
319 def warning(string):
320         global warnings, loc
321         warnings = warnings + 1
322         print "===> Warning:"
323         size = len(loc.stack)
324         i = 0
325         while(i < size -1):
326                 print loc.stack[i].at()
327                 i = i + 1
328         print "%s: %s"% (loc.at(), string)
329
330
331 # -----------------------------------------------------------------------------
332 #                    statements 
333 # -----------------------------------------------------------------------------
334
335 def getvalue(dict, name):
336         if name not in dict.keys(): 
337                 if (debug >1):
338                         print 'Undefined:', name
339                 return 0
340         v = dict.get(name, 0)
341         if (debug > 1):
342                 print "getvalue %s returning %s" % (name, v)
343         return v
344
345 def setvalue(dict, name, value):
346         if name in dict.keys(): 
347                 print "Warning, %s previously defined" % name
348         if (debug > 1):
349                 print "setvalue sets %s to %s" % (name, value)
350         dict[name] = value
351
352 # options. 
353 # to create an option, it has to not exist. 
354 # When an option value is fetched, the fact that it was used is 
355 # remembered. 
356 # Legal things to do:
357 # set a default value, then set a real value before the option is used.
358 # set a value, try to set a default, default silently fails.
359 # Illegal:
360 # use the value, then try to set the value
361
362 def newoption(name):
363         o = getvalue(options, name)
364         if (o):
365                 print "option %s already defined" % name
366                 sys.exit(1)
367         o = option(name)
368         setvalue(options, name, o)
369         options_by_order.append(name)
370
371 # option must be declared before being used in a part
372 # if we're not processing a part, then we must
373 # be at the top level where all options are available
374 def getoption(name, part):
375         global options
376         if (part):
377                 o = getvalue(part.options, name)
378         else:
379                 o = getvalue(options, name)
380         if (o == 0 or not o.defined):
381                 error("Error: Option %s undefined (missing use command?)." % name)
382                 return
383         v = o.getvalue(part)
384         if (debug > 2):
385                 print "getoption returns %s" % v
386                 print "%s" % o.where()
387         return v
388
389 # setoptionstmt only allowed at top level
390 def setoptionstmt(name, value):
391         global curpart
392         if (curpart != root):
393                 fatal("Error: options can only be set in target configuration file")
394         setoption(name, value)
395
396 def setoption(name, value):
397         global loc
398         o = getvalue(options, name)
399         if (o == 0):
400                 fatal("Error: attempt set nonexistent option %s" % name)
401         o.setvalue(value, loc)
402
403 def setdefault(name, value):
404         global loc
405         o = getvalue(options, name)
406         if (not o):
407                 return
408         if (o.default):
409                 print "setdefault: attempt to duplicate default for %s" % name
410                 return
411         o.setdefault(value, loc)
412
413 def setnodefault(name):
414         global loc
415         o = getvalue(options, name)
416         if (not o):
417                 return
418         if (o.default):
419                 print "setdefault: attempt to duplicate default for %s" % name
420                 return
421         o.setnodefault(loc)
422
423 def setcomment(name, value):
424         o = getvalue(options, name)
425         if (not o):
426                 fatal("setcomment: %s not here" % name)
427         o.setcomment(value, loc)
428
429 def setexported(name):
430         o = getvalue(options, name)
431         if (not o):
432                 fatal("setexported: %s not here" % name)
433         o.setexported()
434
435 def setnoexport(name):
436         o = getvalue(options, name)
437         if (not o):
438                 fatal("setnoexport: %s not here" % name)
439         o.setnoexport()
440
441 def setexportable(name):
442         o = getvalue(options, name)
443         if (not o):
444                 fatal("setexportable: %s not here" % name)
445         o.setexportable()
446
447 def setformat(name, fmt):
448         o = getvalue(options, name)
449         if (not o):
450                 fatal("setformat: %s not here" % name)
451         o.setformat(fmt)
452
453 def getformated(name, part):
454         global options
455         if (part):
456                 o = getvalue(part.options, name)
457         else:
458                 o = getvalue(options, name)
459         if (o == 0 or not o.defined):
460                 fatal( "Error: Option %s undefined (missing use command?)." % name)
461         v = o.getvalue(part)
462         f = o.getformat()
463         return (f % v)
464
465 def isexported(name, part):
466         if (part):
467                 o = getvalue(part.options, name)
468         else:
469                 o = getvalue(options, name)
470         if (o):
471                 return o.isexported()
472         return 0
473
474 def isdefined(name, part):
475         if (part):
476                 o = getvalue(part.options, name)
477         else:
478                 o = getvalue(options, name)
479         if (o):
480                 return o.isdefined()
481         return 0
482
483 def isset(name, part):
484         if (part):
485                 o = getvalue(part.options, name)
486         else:
487                 o = getvalue(options, name)
488         if (o):
489                 return o.isset()
490         return 0
491
492 def isused(name, part):
493         if (part):
494                 o = getvalue(part.options, name)
495         else:
496                 o = getvalue(options, name)
497         if (o):
498                 return o.isused()
499         return 0
500
501 def usesoption(name):
502         global curpart
503         curpart.usesoption(name)
504
505 def validdef(name, defval):
506         o = getvalue(options, name)
507         if (not o):
508                 fatal("validdef: %s not here" % name)
509         if ((defval & 1) != 1):
510             fatal("Error: must specify default value for option %s" % name)
511         if ((defval & 2) != 2):
512             fatal("Error: must specify export for option %s" % name)
513         if ((defval & 4) != 4):
514             fatal("Error: must specify comment for option %s" % name)
515
516 def loadoptions():
517         global treetop
518         optionsfile = os.path.join(treetop, 'src', 'config', 'Options.lb')
519         loc.push_file(optionsfile)
520         if (not parse('options', open(optionsfile, 'r').read())):
521                 fatal("Error: Could not parse file")
522         loc.pop_file()
523
524 # we do the crt0include as a dictionary, so that if needed we
525 # can trace who added what when. Also it makes the keys
526 # nice and unique. 
527 def addcrt0include(path):
528         global crt0includes
529         #fullpath = os.path.join(curdir, path)
530         #fullpath = path
531         #setvalue(crt0includes, fullpath, loc)
532         # oh shoot. Order matters. All right, we'll worry about this 
533         # later. 
534         fullpath = path
535         if (debug > 2):
536                 print "ADDCRT0: %s" % fullpath
537         crt0includes.append(fullpath)
538
539 def addldscript(path):
540         global ldscripts
541         if (path[0] == '/'):
542                 fullpath =  treetop + '/src/' + path
543         else:
544                 fullpath = curdir + '/' + path
545         #fullpath = os.path.join(curdir, path)
546         #setvalue(ldscripts, fullpath, loc)
547         if (debug):
548                 print "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path)
549         ldscripts.append(fullpath)
550
551 def payload(path):
552         global payloadfile
553         adduserdefine("PAYLOAD:=%s"%path)
554 #       addrule('payload')
555 #       adddep('payload', path)
556 #       addaction('payload', 'cp $< $@')
557
558 # this is called with an an object name. 
559 # the easiest thing to do is add this object to the current 
560 # component.
561 # such kludgery. If the name starts with '.' then make the 
562 # dependency be on ./thing.x gag me.
563 def addobjectdriver(dict, object_name):
564         suffix = object_name[-2:]
565         if (suffix == '.o'):
566                 suffix = '.c'
567         base = object_name[:-2]
568         if (object_name[0] == '.'):
569                 source = base + suffix
570         else:
571                 source = os.path.join(curdir, base + suffix)
572         object = base + '.o'
573         if (debug):
574                 print "add object %s source %s" % (object_name, source)
575         setvalue(dict, base, [object, source])
576
577 def addobject(object_name):
578         addobjectdriver(objectrules, object_name)
579
580 def adddriver(driver_name):
581         addobjectdriver(driverrules, driver_name)
582
583 def target(targ_name):
584         global target_dir
585         global curpart
586         global root
587         print "Configuring TARGET %s" % targ_name
588         target_dir = os.path.join(os.path.dirname(loc.file()), targ_name)
589         if not os.path.isdir(target_dir):
590                 print "Creating directory %s" % target_dir
591                 os.makedirs(target_dir)
592         print "Will place Makefile, crt0.S, etc. in %s" % target_dir
593         root = partobj(target_dir, 0, 'board')
594         curpart = root
595
596 def part(name, path, file):
597         global curpart,curdir,treetop
598         dirstack.append(curdir)
599         curdir = os.path.join(treetop, 'src', name, path)
600         newpart = partobj(curdir, curpart, name)
601         print "Configuring PART %s" % name
602         if (debug):
603                 print "PUSH part %s %s" % (name, curpart.dir)
604         pstack.push(curpart)
605         curpart = newpart
606         doconfigfile(curdir, file)
607
608 def partpop():
609         global curpart,curdir
610         print "End PART %s" % curpart.type
611         # Warn if options are used without being set in this part
612         for i in curpart.options.keys():
613                 if (not isset(i, curpart)):
614                         print "WARNING: Option %s using default value %s" % (i, getformated(i, curpart))
615         curpart = pstack.pop()
616         curdir = dirstack.pop()
617
618 # dodir is like part but there is no new part
619 def dodir(path, file):
620         global curdir,  treetop
621         # if the first char is '/', it is relative to treetop, 
622         # else relative to curdir
623         # os.path.join screws up if the name starts with '/', sigh.
624         if (path[0] == '/'):
625                 fullpath = treetop + '/src/' + path 
626         else:
627                 fullpath = os.path.join(curdir,  path)
628         if (debug):
629                 print "DODIR: path %s, fullpath %s" % (path, fullpath)
630                 print "DODIR: curdis %s treetop %s" % (curdir, treetop)
631         print "Configuring DIR %s" % os.path.join(path, file)
632         dirstack.append(curdir)
633         curdir = fullpath
634         file = os.path.join(fullpath, file)
635         config_file_list.append(file)
636         doconfigfile(fullpath, file)
637         curdir = dirstack.pop()
638
639 def lookup(name):
640     global curpart
641     v = getoption(name, curpart)
642     exitiferrors()
643     return v
644
645 def ternary(val, yes, no):
646         if (debug):
647                 print "ternary %s" % expr
648         if (debug):
649                 print "expr %s a %d yes %d no %d"% (expr, a, yes, no)
650         if (val == 0):
651                 if (debug):
652                     print "Ternary returns %d" % yes
653                 return yes
654         else:
655                 if (debug):
656                         print "Ternary returns %d" % no
657                 return no
658
659 # atoi is in the python library, but not strtol? Weird!
660 def tohex(name):
661         return eval('int(%s)' % name)
662
663 def IsInt( str ):
664         """ Is the given string an integer?"""
665         try:
666                 num = int(str)
667                 return 1
668         except ValueError:
669                 return 0
670
671 def addrule(id):
672         o = makerule(id)
673         setvalue(makebaserules, id, o)
674         
675 def adduserdefine(str):
676         userdefines.append(str)
677
678 def dequote(str):
679         a = re.sub("^\"", "", str)
680         a = re.sub("\"$", "", a)
681         # highly un-intuitive, need four \!
682         a = re.sub("\\\\\"", "\"", a)
683         return a
684
685 def addaction(id, str):
686         o = getvalue(makebaserules, id)
687         a = dequote(str)
688         o.addaction(a)
689
690 def adddep(id, str):
691         o = getvalue(makebaserules, id)
692         a = dequote(str)
693         o.adddependency(a)
694
695 # If the first part of <path> matches treetop, replace that part with "$(TOP)"
696 def topify(path):
697         global treetop
698         if path[0:len(treetop)] == treetop:
699                 path = path[len(treetop):len(path)]
700                 if (path[0:1] == "/"):
701                         path = path[1:len(path)]
702                 path = "$(TOP)/" + path
703         return path
704
705 # arch is 'different' ... darn it.
706 def set_arch(my_arch):
707         global arch
708         global curdir
709         arch = my_arch
710         setoption('ARCH', my_arch)
711         part('arch', my_arch, 'config/make.base.lb')
712
713
714 def mainboard(path):
715         global mainboard_dir, treetop
716         mainboard_dir = path
717         full_mainboard_dir = os.path.join(treetop, 'src/mainboard', path)
718         setoption('MAINBOARD', full_mainboard_dir)
719         vendor = re.sub("/.*", "", path)
720         mainboard_part_number = re.sub("[^/]/", "", path)
721         setoption('MAINBOARD_VENDOR', vendor)
722         setoption('MAINBOARD_PART_NUMBER', mainboard_part_number)
723         part('mainboard', path, 'Config.lb')
724
725 #=============================================================================
726 #               FILE OUTPUT 
727 #=============================================================================
728 def writemakefileheader(file, fname):
729         file.write("# File: %s\n" % fname)
730         file.write("# This file was generated by '%s %s %s'\n\n"
731                 % (sys.argv[0], sys.argv[1], sys.argv[2]))
732
733
734 def writemakefilesettings(path):
735         global treetop, arch, mainboard_dir, target_dir, options_by_order, root
736         # Write Makefile.settings to seperate the settings
737         # from the actual makefile creation
738         # In practice you need to rerun NLBConfig.py to change
739         # these but in theory you shouldn't need to.
740
741         filename = os.path.join(path, "Makefile.settings")
742         print "Creating", filename
743         file = open(filename, 'w+')
744         writemakefileheader(file, filename)
745         file.write("TOP:=%s\n" % (treetop))
746         #file.write("ARCH:=%s\n" % (arch))
747         #file.write("MAINBOARD:=%s\n" % (mainboard_dir))
748         file.write("TARGET_DIR:=%s\n" % (target_dir))
749         for i in options_by_order:
750                 if (isexported(i, 0)):
751                         file.write("export %s:=%s\n" % (i, getformated(i, 0)))
752         file.write("export VARIABLES := ")
753         for i in options.keys():
754                 if (isexported(i, 0)):
755                         file.write("%s " % i)
756         file.write("\n")
757 #       file.write("CPUFLAGS := ")
758 #       for i in options.keys():
759 #               o = options[i]
760 #               file.write("-D%s=%s " % (i, o.getvalue()))
761 #       file.write("\n")
762         file.close()
763
764
765 # write the makefile
766 # let's try the Makefile
767 # first, dump all the -D stuff
768
769 def writemakefile(path):
770         global root
771         makefilepath = os.path.join(path, "Makefile")
772         print "Creating", makefilepath
773         file = open(makefilepath, 'w+')
774         writemakefileheader(file, makefilepath)
775
776         # file.write("include Makefile.settings\n")
777         # file.write("include cpuflags\n")
778         # Putting "include cpuflags" in the Makefile has the problem that the
779         # cpuflags file would be generated _after_ we want to include it.
780         # Instead, let make do the work of computing CPUFLAGS:
781         file.write("""\
782 # Get the value of TOP, VARIABLES, and several other variables.
783 include Makefile.settings
784
785 # Function to create an item like -Di586 or -DMAX_CPUS='1' or -Ui686
786 D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)
787
788 # Compute the value of CPUFLAGS here during make's first pass.
789 CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))
790 """)
791
792         for i in userdefines:
793                 file.write("%s\n" %i)
794         file.write("\n")
795
796         # print out all the object dependencies
797         file.write("\n# object dependencies (objectrules:)\n")
798         file.write("OBJECTS :=\n")
799         file.write("DRIVERS :=\n")
800         for objrule in objectrules.keys():
801                 obj = objectrules[objrule]
802                 obj_name = obj[0]
803                 obj_source = obj[1]
804                 file.write("OBJECTS-1 += %s\n" % (obj_name))
805
806         for driverrule in driverrules.keys():
807                 driver = driverrules[driverrule]
808                 obj_name = driver[0]
809                 obj_source = driver[1]
810                 file.write("DRIVER += %s\n" % (obj_name))
811
812         # Print out all ldscript.ld dependencies.
813         file.write("\n# ldscript.ld dependencies:\n")
814         file.write("LDSUBSCRIPTS-1 := \n" )
815         for script in ldscripts:
816                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
817
818         # Print out the dependencies for crt0_includes.h
819         file.write("\n# Dependencies for crt0_includes.h\n")
820         file.write("CRT0_INCLUDES:=\n")
821         for i in crt0includes:
822                 if (local_path.match(i)):
823                         file.write("CRT0_INCLUDES += %s\n" % i)
824                 else:
825                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % i)
826
827         file.write("\nSOURCES=\n")
828         #for source in sources:
829                 #file.write("SOURCES += %s\n" % source)
830         
831         # Print out the user defines.
832         file.write("\n# userdefines:\n")
833         #for udef in userdefines:
834                 #file.write("%s\n" % udef)
835                 
836         # Print out the base rules.
837         # Need to have a rule that counts on 'all'.
838         file.write("\n# mainrulelist:")
839         #file.write("\nmainrule: %s\n" % mainrulelist)
840
841         # Print out any user rules.
842         file.write("\n# From makerule or docipl commands:\n")
843         # Old way (hash order): for target in makebaserules.keys():
844         # New way (config file order):
845         #for target in makerule_targets:
846                 #makebaserules[target].write(file)
847
848         file.write("\n# objectrules:\n")
849         for objrule in objectrules.keys():
850                 obj = objectrules[objrule]
851                 source = topify(obj[1])
852                 file.write("%s: %s\n" % (obj[0], source))
853                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
854                 #file.write("%s\n" % objrule[2])
855
856         for driverrule in driverrules.keys():
857                 driver = driverrules[driverrule]
858                 source = topify(driver[1])
859                 file.write("%s: %s\n" % (driver[0], source))
860                 #file.write("%s\n" % objrule[2])
861
862         # Print out the rules that will make cause the files
863         # generated by NLBConfig.py to be remade if any dependencies change.
864
865         file.write("\n# Remember the automatically generated files\n")
866         file.write("GENERATED:=\n")
867         for genfile in [ 'Makefile',
868                         'Makefile.settings',
869                         'crt0_includes.h',
870                         'nsuperio.c',
871                          'chip.c', 
872                         'LinuxBIOSDoc.config' ]:
873                 file.write("GENERATED += %s\n" % genfile)
874
875         file.write("\n# Remake Makefile (and the other files generated by\n")
876         file.write("# NLBConfig.py) if any config dependencies change.\n")
877
878         for cfile in config_file_list:
879                 file.write("$(GENERATED): %s\n" % topify(cfile))
880
881         for depfile in [ '%s' % top_config_file,    # This a duplicate, remove?
882                         '$(TOP)/util/config/NLBConfig.py',
883                         '$(TOP)/src/arch/$(ARCH)/config/make.base' ]:
884                 file.write("$(GENERATED): %s\n" % depfile)
885
886         file.write("$(GENERATED):\n")
887         file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n"
888                         % top_config_file)
889
890         keys = root.options.keys()
891         keys.sort()
892         file.write("\necho:\n")
893         for key in keys:
894                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
895         
896
897         for i in makebaserules.keys():
898                 m = makebaserules[i]
899                 file.write("%s: " %i)
900                 for i in m.dependency:
901                         file.write("%s " % i)
902                 file.write("\n")
903                 for i in m.actions:
904                         file.write("\t%s\n" % i)
905         file.close()
906
907 # Write out crt0_includes.h (top-level assembly language) include file.
908 def writecrt0_includes(path):
909         crt0filepath = os.path.join(path, "crt0_includes.h")
910         print "Creating", crt0filepath
911         file = open(crt0filepath, 'w+')
912
913         for i in crt0includes:
914                 file.write("#include <%s>\n" % i)
915
916         file.close()
917
918
919 %%
920 parser Config:
921     ignore:                     r'\s+'
922     ignore:                     "#.*?\r?\n"
923
924     # less general tokens should come first, otherwise they get matched
925     # by the re's
926     token ACT:                  'act'
927     token ADDACTION:            'addaction'
928     token ALWAYS:               'always'
929     token ARCH:                 'arch'
930     token COMMENT:              'comment'
931     token CPU:                  'cpu'
932     token DEFAULT:              'default'
933     token DEFINE:               'define'
934     token DEP:                  'dep'
935     token DIR:                  'dir'
936     token DRIVER:               'driver'
937     token ELSE:                 'else'
938     token END:                  '$|end'
939     token EQ:                   '='
940     token EXPORT:               'export'
941     token FORMAT:               'format'
942     token IF:                   'if'
943     token INIT:                 'init'
944     token LDSCRIPT:             'ldscript'
945     token LOADOPTIONS:          'loadoptions'
946     token MAINBOARD:            'mainboard'
947     token MAINBOARDINIT:        'mainboardinit'
948     token MAKEDEFINE:           'makedefine'
949     token MAKERULE:             'makerule'
950     token NEVER:                'never'
951     token NONE:                 'none'
952     token NORTHBRIDGE:          'northbridge'
953     token OBJECT:               'object'
954     token OPTION:               'option'
955     token PAYLOAD:              'payload'
956     token PMC:                  'pmc'
957     token REGISTER:             'register'
958     token SOUTHBRIDGE:          'southbridge'
959     token SUPERIO:              'superio'
960     token TARGET:               'target'
961     token USED:                 'used'
962     token USES:                 'uses'
963     token NUM:                  r'[0-9]+'
964     token XNUM:                 r'0x[0-9a-fA-F]+'
965     # Why is path separate? Because paths to resources have to at least
966     # have a slash, we thinks
967     token PATH:                 r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+'
968     # Dir's on the other hand are abitrary
969     # this may all be stupid.
970     token DIRPATH:              r'[a-zA-Z0-9_$()./]+'
971     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
972     token DELEXPR:              r'{([^}]+|\\.)*}'
973     token STR:                  r'"([^\\"]+|\\.)*"'
974     token RAWTEXT:              r'.*'
975
976     rule expr:          logical                 {{ l = logical }}
977                         ( "&&" logical          {{ l = l and logical }}
978                         | "||"  logical         {{ l = l or logical }}
979                         )*                      {{ return l }}
980
981     rule logical:       factor                  {{ n = factor }}
982                         ( "[+]" factor          {{ n = n+factor }}
983                         | "-"  factor           {{ n = n-factor }}
984                         )*                      {{ return n }}
985
986     rule factor:        term                    {{ v = term }}
987                         ( "[*]" term            {{ v = v*term }}
988                         | "/"  term             {{ v = v/term }}
989                         | "<<"  term            {{ v = v << term }}
990                         | ">=" term             {{ v = (v < term)}}
991                         )*                      {{ return v }}
992
993     # A term is a number, variable, or an expression surrounded by parentheses
994     rule term:          NUM                     {{ return atoi(NUM) }}
995                 |       XNUM                    {{ return tohex(XNUM) }}
996                 |       ID                      {{ return lookup(ID) }}
997                 |       unop                    {{ return unop }}
998                 |       "\\(" expr "\\)"        {{ return expr }}
999
1000     rule unop:          "!" expr                {{ return not(expr) }}
1001
1002     rule partend<<C>>:  (stmt<<C>>)* END        {{ partpop()}}
1003
1004     rule mainboard:     MAINBOARD PATH          {{ mainboard(PATH) }}
1005                         partend<<1>>
1006                         
1007     rule northbridge<<C>>:
1008                         NORTHBRIDGE PATH        {{ if (C): part('northbridge', PATH, 'Config.lb') }}
1009                         partend<<C>>
1010
1011     rule superio<<C>>:  SUPERIO PATH            {{ if (C): part('superio', PATH, 'Config.lb') }}
1012                         partend<<C>>
1013
1014     rule cpu<<C>>:      CPU ID                  {{ if (C): part('cpu', ID, 'Config.lb') }}
1015                         partend<<C>>
1016
1017     rule pmc<<C>>:      PMC PATH                {{ if (C): part('pmc', PATH, 'Config.lb') }}
1018                         partend<<C>>
1019
1020     rule arch<<C>>:     ARCH ID                 {{ if (C): set_arch(ID) }}
1021                         partend<<C>>
1022
1023     rule southbridge<<C>>:
1024                         SOUTHBRIDGE PATH        {{ if (C): part('southbridge', PATH, 'Config.lb')}}
1025                         partend<<C>>
1026
1027     rule mainboardinit<<C>>: 
1028                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1029
1030     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1031
1032     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1033
1034     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1035
1036     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1037
1038     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1039
1040 # if is a bad id ....
1041 # needs to be C and ID, but nested if's are, we hope, not going to 
1042 # happen. IF so, possibly ID && C could be used.
1043     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1044                         (stmt<<c>>)* [ ELSE (stmt<<not c>>)* ] END
1045
1046     rule depsacts<<ID, C>>:
1047                         ( DEP STR               {{ if (C): adddep(ID, STR) }}
1048                         | ACT STR               {{ if (C): addaction(ID, STR) }}
1049                         )*
1050
1051     rule makerule<<C>>: MAKERULE DIRPATH        {{ if (C): addrule(DIRPATH) }} 
1052                         depsacts<<DIRPATH, C>> 
1053
1054     rule makedefine<<C>>:
1055                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1056
1057     rule addaction<<C>>:
1058                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1059
1060     rule init<<C>>:     INIT STR                {{ if (C): curpart.addinit(STR) }}
1061
1062     rule register<<C>>: REGISTER STR            {{ if (C): curpart.addregister(STR) }}
1063
1064 # to make if work without 2 passses, we use an old hack from SIMD, the 
1065 # context bit. If the bit is 1, then ops get done, otherwise
1066 # ops don't get done. From the top level, context is always
1067 # 1. In an if, context depends on eval of the if condition
1068     rule stmt<<C>>:     cpu<<C>>                {{ return cpu}}
1069                 |       pmc<<C>>                {{ return pmc}}
1070                 |       arch<<C>>               {{ return arch}}
1071                 |       northbridge<<C>>        {{ return northbridge }}
1072                 |       southbridge<<C>>        {{ return southbridge }}
1073                 |       superio<<C>>            {{ return superio }}
1074                 |       object<<C>>             {{ return object }}
1075                 |       driver<<C>>             {{ return driver }}
1076                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1077                 |       makerule<<C>>           {{ return makerule }}
1078                 |       makedefine<<C>>         {{ return makedefine }}
1079                 |       addaction<<C>>          {{ return addaction }}
1080                 |       init<<C>>               {{ return init }}
1081                 |       register<<C>>           {{ return register}}
1082                 |       iif<<C>>                {{ return iif }}
1083                 |       dir<<C>>                {{ return dir}}
1084                 |       ldscript<<C>>           {{ return ldscript}}
1085                 |       payload<<C>>            {{ return payload}}
1086
1087     # ENTRY for parsing Config.lb file
1088     rule cfgfile:       (uses<<1>>)* (stmt<<1>>)*
1089                                                 {{ return 1 }}
1090
1091     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1092
1093     rule uses<<C>>:     USES (usesid<<C>>)+
1094
1095     rule value:         STR                     {{ return dequote(STR) }} 
1096                 |       expr                    {{ return expr }}
1097                 |       DELEXPR                 {{ return DELEXPR }}
1098
1099     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoptionstmt(ID, value) }}
1100
1101     rule opif:          IF ID                   {{ c = lookup(ID) }}
1102                         (option<<c>>)* [ ELSE (option<<not c>>)* ] END
1103
1104     rule opstmt:        option<<1>>
1105                 |       opif
1106
1107     # ENTRY for parsing a delayed value
1108     rule delexpr:       "{" expr "}"            {{ return expr }}
1109
1110     # ENTRY for parsing root part
1111     rule board:         LOADOPTIONS             {{ loadoptions() }}
1112                         TARGET DIRPATH          {{ target(DIRPATH) }}
1113                         (uses<<1>>)*
1114                         (opstmt)*
1115                         mainboard               {{ return 1 }}
1116
1117     rule defstmts<<ID>>:                        {{ d = 0 }}
1118                         ( DEFAULT
1119                           ( value               {{ setdefault(ID, value) }}
1120                           | NONE                {{ setnodefault(ID) }}
1121                           )                     {{ d = d | 1 }}
1122                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1123                         | EXPORT 
1124                           ( ALWAYS              {{ setexported(ID) }}
1125                           | USED                {{ setexportable(ID) }}
1126                           | NEVER               {{ setnoexport(ID) }}
1127                           )                     {{ d = d | 2 }}
1128                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1129                         )+                      {{ return d }}
1130                 
1131     rule define:        DEFINE ID               {{ newoption(ID) }}
1132                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
1133
1134     # ENTRY for parsing Options.lb file
1135     rule options:       (define)* END           {{ return 1 }}
1136 %%
1137
1138 def dumptree(part, lvl):
1139         if (debug):
1140                 print "DUMPTREE ME is"
1141         part.dumpme(lvl)
1142         # dump the siblings -- actually are there any? not sure
1143         # dump the kids
1144         if (debug):
1145                 print "DUMPTREE KIDS are"
1146         for kid in part.children:
1147                 dumptree(kid, lvl+1)
1148         if (debug):
1149                 print "DONE DUMPTREE"
1150
1151 def gencode(part):
1152         if (debug):
1153                 print "GENCODE ME is"
1154         if (debug):
1155                 part.gencode()
1156         # dump the siblings -- actually are there any? not sure
1157         # dump the kids
1158         if (debug):
1159                 print "GENCODE KIDS are"
1160         for kid in part.children:
1161                 gencode(kid)
1162         if (debug):
1163                 print "DONE GENCODE"
1164         
1165
1166 def doconfigfile(path, file):
1167         filename = os.path.join(path, file)
1168         loc.push_file(filename)
1169         if (not parse('cfgfile', open(filename, 'r').read())):
1170                 fatal("Error: Could not parse file")
1171         exitiferrors()
1172
1173 if __name__=='__main__':
1174         from sys import argv
1175         if (len(argv) < 3):
1176                 print 'Args: <file> <path to linuxbios>'
1177                 sys.exit(1)
1178
1179         top_config_file = os.path.abspath(sys.argv[1])
1180
1181         treetop = os.path.abspath(sys.argv[2])
1182
1183         # Now read in the customizing script...
1184         loc.push_file(argv[1])
1185         if (not parse('board', open(argv[1], 'r').read())):
1186                 fatal("Error: Could not parse file")
1187
1188         if (debug):
1189                 print "DEVICE TREE:"
1190                 dumptree(root, 0)
1191
1192         gencode(root)
1193
1194         # crt0 includes
1195         if (debug):
1196                 for i in crt0includes:
1197                         print "crt0include file %s" % (i)
1198                 for i in driverrules.keys():
1199                         print "driver file %s" % (i)
1200                 for i in ldscripts:
1201                         print "ldscript file %s" % (i)
1202                 for i in makebaserules.keys():
1203                         m = makebaserules[i]
1204                         print " makerule %s dep %s act %s" % (i, m.dependency, m.actions)
1205
1206         writemakefilesettings(target_dir)
1207         writecrt0_includes(target_dir)
1208         writemakefile(target_dir)