fix crt0 includes ordering
[coreboot.git] / util / newconfig / config.g
1 import sys
2 import os
3 import re
4 import string
5
6 warnings = 0
7 errors = 0
8
9 target_dir = ''
10 target_name = ''
11 treetop = ''
12 global_options = {}
13 global_options_by_order = []
14 global_option_values = {}
15 global_uses_options = {}
16 romimages = {}
17 buildroms = []
18 curimage = 0
19 alloptions = 0 # override uses at top level
20
21 local_path = re.compile(r'^\.')
22 include_pattern = re.compile(r'%%([^%]+)%%')
23
24 # -----------------------------------------------------------------------------
25 #                    Utility Classes
26 # -----------------------------------------------------------------------------
27
28 class stack:
29         """Used to keep track of the current part or dir"""
30         class __stack_iter:
31                 def __init__ (self, stack):
32                         self.index = 0
33                         self.len = len(stack)
34                         self.stack = stack
35
36                 def __iter__ (self):
37                         return self
38
39                 def next (self):
40                         if (self.index < self.len):
41                                 s = self.stack[self.index]
42                                 self.index = self.index + 1
43                                 return s
44                         raise StopIteration
45
46         def __init__ (self):
47                 self.stack = []
48
49         def __len__ (self):
50                 return len(self.stack)
51
52         def __getitem__ (self, i):
53                 try:
54                         return self.stack[i]
55                 except IndexError:
56                         return 0
57
58         def __iter__ (self):
59                 return self.__stack_iter(self.stack)
60
61         def push(self, part):
62                 self.stack.append(part)
63
64         def pop(self):
65                 try:
66                         return self.stack.pop()
67                 except IndexError:
68                         return 0
69
70         def tos(self):
71                 try:
72                         return self.stack[-1]
73                 except IndexError:
74                         return 0
75
76         def empty(self):
77                 return (len(self.stack) == 0)
78 partstack = stack()
79 dirstack = stack()
80
81 class debug_info:
82         none = 0
83         gencode = 1
84         dumptree = 2
85         object = 3
86         dict = 4
87         statement = 5
88         dump = 6
89
90         def __init__(self, *level):
91                 self.__level = level
92
93         def setdebug(self, *level):
94                 self.__level = level
95
96         def level(self, level):
97                 return level in self.__level
98
99         def info(self, level, str):
100                 if level in self.__level:
101                         print str
102
103 global debug
104 debug = debug_info(debug_info.none)
105
106 # -----------------------------------------------------------------------------
107 #                    Error Handling
108 # -----------------------------------------------------------------------------
109
110 class location:
111         """Used to keep track of our current location while parsing
112         configuration files"""
113         class __place:
114                 def __init__(self, file, line, command):
115                         self.file = file
116                         self.line = line
117                         self.command = command
118                 def next_line(self, command):
119                         self.line = self.line + 1
120                         self.command = command
121                 def at(self):
122                         return "%s:%d" % (self.file, self.line)
123         
124         def __init__ (self):
125                 self.stack = stack()
126
127         def __str__ (self):
128                 s = ''
129                 for p in self.stack:
130                         if (s == ''):
131                                 s = p.at()
132                         else:
133                                 s = s + '\n' + p.at()
134                 return s
135
136         def file(self):
137                 return self.stack.tos().file
138
139         def line(self):
140                 return self.stack.tos().line
141
142         def command(self):
143                 return self.stack.tos().command
144
145         def push(self, file):
146                 self.stack.push(self.__place(os.path.normpath(file), 0, ""))
147
148         def pop(self):
149                 self.stack.pop()
150
151         def next_line(self, command):
152                 self.stack.tos().next_line(command)
153
154         def at(self):
155                 return self.stack.tos().at()
156 loc = location()
157
158 def error(string):      
159         """Print error message"""
160         global errors, loc
161         errors = errors + 1
162         print "===> ERROR: %s" % string
163         print "%s" % loc
164
165 def fatal(string):      
166         """Print error message and exit"""
167         error(string)
168         exitiferrors()
169
170 def warning(string):
171         """Print warning message"""
172         global warnings, loc
173         warnings = warnings + 1
174         print "===> Warning: %s" % string
175         print "%s" % loc
176
177 def exitiferrors():
178         """Exit parser if an error has been encountered"""
179         if (errors != 0):
180                 sys.exit(1)
181
182 # -----------------------------------------------------------------------------
183 #                    Main classes
184 # -----------------------------------------------------------------------------
185
186 class romimage:
187         """A rom image is the ultimate goal of linuxbios"""
188         def __init__ (self, name):
189                 self.name = name
190                 self.arch = ''
191                 self.payload = ''
192                 self.initfile = ''
193                 self.makebaserules = {}
194                 self.objectrules = {}
195                 self.initobjectrules = {}
196                 self.driverrules = {}
197                 self.ldscripts = []
198                 self.userdefines = []
199                 self.initincludes = {}
200                 self.initincludesorder = [] # need to preserve order
201                 self.useinitincludes = 0 # transitional
202                 self.partinstance = 0
203                 self.root = 0
204                 self.target_dir = ''
205                 self.values = {} # values of options set in romimage
206
207         def getname(self):
208                 return self.name
209
210         def getvalues(self):
211                 return self.values
212
213         def setarch(self, arch):
214                 self.arch = arch
215
216         def setpayload(self, payload):
217                 self.payload = payload
218
219         def setinitfile(self, initfile):
220                 self.initfile = initfile
221
222         def getinitfile(self):
223                 return self.initfile
224
225         def addmakerule(self, id):
226                 o = getdict(self.makebaserules, id)
227                 if (o):
228                         print "Warning, rule %s previously defined" % id
229                 o = makerule(id)
230                 setdict(self.makebaserules, id, o)
231
232         def getmakerules(self):
233                 return self.makebaserules
234
235         def getmakerule(self, id):
236                 o = getdict(self.makebaserules, id)
237                 if (o):
238                         return o
239                 fatal("No such make rule \"%s\"" % id);
240
241         def addmakeaction(self, id, str):
242                 o = getdict(self.makebaserules, id)
243                 if (o):
244                         a = dequote(str)
245                         o.addaction(a)
246                         return
247                 fatal("No such rule \"%s\" for addmakeaction" % id);
248
249         def addmakedepend(self, id, str):
250                 o = getdict(self.makebaserules, id)
251                 if (o):
252                         a = dequote(str)
253                         o.adddependency(a)
254                         return
255                 fatal("No such rule \"%s\" for addmakedepend" % id);
256
257         # this is called with an an object name. 
258         # the easiest thing to do is add this object to the current 
259         # component.
260         # such kludgery. If the name starts with '.' then make the 
261         # dependency be on ./thing.x gag me.
262         def addobjectdriver(self, dict, object_name):
263                 global dirstack
264                 suffix = object_name[-2:]
265                 if (suffix == '.o'):
266                         suffix = '.c'
267                 base = object_name[:-2]
268                 if (object_name[0] == '.'):
269                         source = base + suffix
270                 else:
271                         source = os.path.join(dirstack.tos(), base + suffix)
272                 object = base + '.o'
273                 debug.info(debug.object, "add object %s source %s" % (object_name, source))
274                 l = getdict(dict, base)
275                 if (l):
276                         print "Warning, object/driver %s previously defined" % base
277                 setdict(dict, base, [object, source])
278
279         def addinitobjectrule(self, name):
280                 self.addobjectdriver(self.initobjectrules, name)
281
282         def addobjectrule(self, name):
283                 self.addobjectdriver(self.objectrules, name)
284
285         def adddriverrule(self, name):
286                 self.addobjectdriver(self.driverrules, name)
287
288         def getinitobjectrules(self):
289                 return self.initobjectrules
290
291         def getinitobjectrule(self, name):
292                 o = getdict(self.initobjectrules, name)
293                 if (o):
294                         return o
295                 fatal("No such init object rule \"%s\"" % name);
296
297         def getobjectrules(self):
298                 return self.objectrules
299
300         def getobjectrule(self, name):
301                 o = getdict(self.objectrules, name)
302                 if (o):
303                         return o
304                 fatal("No such object rule \"%s\"" % name);
305
306         def getdriverrules(self):
307                 return self.driverrules
308
309         def getdriverrule(self, name):
310                 o = getdict(self.driverrules, name)
311                 if (o):
312                         return o
313                 fatal("No such driver rule \"%s\"" % name);
314
315         def addldscript(self, path):
316                 self.ldscripts.append(path)
317
318         def getldscripts(self):
319                 return self.ldscripts
320
321         def adduserdefine(self, str):
322                 self.userdefines.append(str)
323
324         def getuserdefines(self):
325                 return self.userdefines
326
327         def addinitinclude(self, str, path):
328                 if (str != 0):
329                         self.useinitincludes = 1
330
331                 debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path))
332                 o = getdict(self.initincludes, path)
333                 if (o):
334                         print "Warning, init include for %s previously defined" % path
335                 o = initinclude(str, path)
336                 setdict(self.initincludes, path, o)
337                 self.initincludesorder.append(path)
338
339         def getinitincludes(self):
340                 return self.initincludesorder
341
342         def getinitinclude(self, path):
343                 o = getdict(self.initincludes, path)
344                 if (o):
345                         return o
346                 fatal("No such init include \"%s\"" % path);
347
348         def getincludefilename(self):
349                 if (self.useinitincludes):
350                         return "crt0.S"
351                 else:
352                         return "crt0_includes.h"
353         
354         def newformat(self):
355                 return self.useinitincludes
356
357         def numparts(self):
358                 return self.partinstance
359
360         def newpartinstance(self):
361                 i = self.partinstance
362                 self.partinstance = self.partinstance + 1
363                 return i
364
365         def setroot(self, part):
366                 self.root = part
367
368         def getroot(self):
369                 return self.root
370
371         def settargetdir(self, path):
372                 self.targetdir = path
373
374         def gettargetdir(self):
375                 return self.targetdir
376
377 class buildrom:
378         """A buildrom statement"""
379         def __init__ (self, size, roms):
380                 self.size = size
381                 self.roms = roms
382
383 class initinclude:
384         """include file for initialization code"""
385         def __init__ (self, str, path):
386                 self.string = str
387                 self.path = path
388
389         def getstring(self):
390                 return self.string
391
392         def getpath(self):
393                 return self.path
394
395 class makerule:
396         """Rule to be included in Makefile"""
397         def __init__ (self, target):
398                 self.target = target
399                 self.dependency = []
400                 self.actions = []
401
402         def addaction(self, action):
403                 self.actions.append(action)
404
405         def adddependency(self, dependency):
406                 self.dependency.append(dependency)
407
408         def gtarget(self):
409                 return self.target
410
411         def gdependency(self):
412                 return self.dependency
413
414         def gaction(self):
415                 return self.actions
416
417 class option:
418         """Configuration option"""
419         def __init__ (self, name):
420                 self.name = name        # name of option
421                 self.loc = 0            # current location
422                 self.set = 0            # option has been set
423                 self.used = 0           # option has been set
424                 self.default = 0        # option has default value (otherwise
425                                         # it is undefined)
426                 self.comment = ''       # description of option
427                 self.exportable = 0     # option is able to be exported
428                 self.exported = 0       # option is exported
429                 self.defined = 0        # option has a value
430                 self.format = '%s'      # option print format
431
432         def setvalue(self, value, values, loc):
433                 self.set = 1
434                 self.defined = 1
435                 self.loc = loc
436                 #self.value = value
437                 setdict(values, self.name, value)
438
439         def getvalue(self, image, values):
440                 global curimage
441                 v = getdict(values, self.name)
442                 if (v == 0):
443                         return 0
444                 val = v.contents()
445                 if (not (type(val) is str)):
446                         return v
447                 if (val == '' or val[0] != '{'):
448                         return v
449                 s = curimage
450                 curimage = image
451                 val = parse('delexpr', val)
452                 curimage = s
453                 # TODO: need to check for parse errors!
454                 return option_value(val)
455
456         def setdefault(self, value, loc):
457                 global global_option_values
458                 if (self.default):
459                         fatal("Error: default value for %s already set" % self.name)
460                 setdict(global_option_values, self.name, value)
461                 self.defined = 1
462                 self.default = 1
463                 self.loc = loc
464
465         def setnodefault(self, loc):
466                 self.default = 1
467                 self.defined = 0
468                 self.loc = loc
469
470         def where(self):
471                 return self.loc
472
473         def setcomment(self, comment, loc):
474                 if (self.comment != ''):
475                         print "%s: " % self.name
476                         print "Attempt to modify comment at %s" % loc 
477                         return
478                 self.comment = comment
479
480         def setexportable(self):
481                 self.exportable = 1
482
483         def setexported(self):
484                 self.exportable = 1
485                 self.exported = 1
486
487         def setnoexport(self):
488                 self.exportable = 0
489                 self.exported = 0
490
491         def setformat(self, fmt):
492                 self.format = fmt
493
494         def getformat(self):
495                 return self.format
496
497         def setused(self):
498                 if (self.exportable):
499                         self.exported = 1
500                 self.used = 1
501
502         def isexported(self):
503                 return (self.exported and self.defined)
504
505 #       def isdefined(self):
506 #               return (self.defined)
507
508         def isset(self):
509                 return (self.set)
510
511 #       def isused(self):
512 #               return (self.used)
513
514 class option_value:
515         """Value of a configuration option"""
516         def __init__(self, value):
517                 self.value = value
518
519         def contents(self):
520                 return self.value
521
522 class partobj:
523         """A configuration part"""
524         def __init__ (self, image, dir, parent, type, name):
525                 debug.info(debug.object, "partobj dir %s parent %s type %s" %(dir,parent,type))
526                 self.image = image
527                 self.children = 0
528                 self.siblings = 0
529                 self.initcode = []
530                 self.registercode = []
531                 # sibling is not a list. 
532                 self.type = type
533                 self.objects = []
534                 self.dir = dir
535                 self.irq = 0
536                 self.instance = image.newpartinstance()
537                 self.flatten_name = flatten_name(type + "/" + name)
538                 debug.info(debug.object, "INSTANCE %d" % self.instance)
539                 self.devfn = 0  
540                 self.private = 0        
541                 self.uses_options = {}
542                 # chip initialization. If there is a chip.h in the 
543                 # directory, generate the structs etc. to 
544                 # initialize the code
545                 if (os.path.exists(dir + "/" + "chip.h")): 
546                         self.chipconfig = 1
547                 else:
548                         self.chipconfig = 0
549                 
550                 if (parent):
551                         debug.info(debug.gencode, "add to parent")
552                         self.parent   = parent
553                         # add current child as my sibling, 
554                         # me as the child.
555                         if (parent.children):
556                                 debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance))
557                                 self.siblings = parent.children
558                         parent.children = self
559                 else:
560                         self.parent = self
561
562         def dumpme(self, lvl):
563                 print "%d: type %s" % (lvl, self.type)
564                 print "%d: instance %d" % (lvl, self.instance)
565                 print "%d: dir %s" % (lvl,self.dir)
566                 print "%d: flatten_name %s" % (lvl,self.flatten_name)
567                 print "%d: parent %s" % (lvl,self.parent.type)
568                 print "%d: parent dir %s" % (lvl,self.parent.dir)
569                 if (self.children):
570                         print "%d: child %s" % (lvl, self.children.dir)
571                 if (self.siblings):
572                         print "%d: siblings %s" % (lvl, self.siblings.dir)
573                 print "%d: initcode " % lvl
574                 for i in self.initcode:
575                         print "  %s" % i
576                 print "%d: registercode " % lvl
577                 for i in self.registercode:
578                         print "  %s" % i
579                 print "\n"
580
581         def gencode(self, file):
582                 if (self.chipconfig):
583                         debug.info(debug.gencode, "gencode: chipconfig(%d)" % self.instance)
584                         file.write("#include \"%s/chip.h\"\n" % self.dir)
585                         file.write("extern struct chip_control %s_control;\n" % \
586                                         self.flatten_name)
587                         file.write("struct %s_config %s_config_%d" % (\
588                                         self.flatten_name ,\
589                                         self.flatten_name , \
590                                         self.instance))
591                         if (self.registercode):
592                                 file.write("\t= {\n")
593                                 for i in self.registercode:
594                                         file.write( "\t  %s" % i)
595                                 file.write("\t};\n")
596                         else:
597                                 file.write(";")
598                         file.write("\n");
599                 if (self.instance):
600                         file.write("struct chip dev%d = {\n" % self.instance)
601                 else:
602                         file.write("struct chip root = {\n")
603                 file.write("/* %s %s */\n" % (self.type, self.dir))
604                 #file.write("  .devfn = %d,\n" % self.devfn)
605                 if (self.siblings):
606                         debug.info(debug.gencode, "gencode: siblings(%d)" % self.siblings.instance)
607                         file.write("  .next = &dev%d,\n" % self.siblings.instance)
608                 if (self.children):
609                         debug.info(debug.gencode, "gencode: children(%d)" % self.children.instance)
610                         file.write("  .children = &dev%d,\n" % \
611                                         self.children.instance)
612                 if (self.private):
613                         file.write("  .private = private%d,\n" % self.instance)
614                 if (self.chipconfig):
615                         # set the pointer to the structure for all this
616                         # type of part
617                         file.write("  .control= &%s_control,\n" % \
618                                         self.flatten_name )
619                         # generate the pointer to the isntance
620                         # of the chip struct
621                         file.write("  .chip_info = (void *) &%s_config_%d,\n" %\
622                                         (self.flatten_name, self.instance ))
623                 file.write("};\n")
624                 
625         def irq(self, irq):
626                 self.irq = irq
627        
628         def addinit(self, code):
629                 self.initcode.append(code)
630                 
631         def addregister(self, code):
632                 code = dequote(code)
633                 self.registercode.append(code)
634
635         def usesoption(self, name):
636                 global global_options
637                 o = getdict(global_options, name)
638                 if (o == 0):
639                         fatal("Error: can't use undefined option %s" % name)
640                 o.setused()
641                 o1 = getdict(self.uses_options, name)
642                 if (o1):
643                         return
644                 setdict(self.uses_options, name, o)
645
646 # -----------------------------------------------------------------------------
647 #                    statements 
648 # -----------------------------------------------------------------------------
649
650 def getdict(dict, name):
651         if name not in dict.keys(): 
652                 debug.info(debug.dict, "Undefined: %s" % name)
653                 return 0
654         v = dict.get(name, 0)
655         debug.info(debug.dict, "getdict %s returning %s" % (name, v))
656         return v
657
658 def setdict(dict, name, value):
659         debug.info(debug.dict, "setdict sets %s to %s" % (name, value))
660         dict[name] = value
661
662 # options. 
663 # to create an option, it has to not exist. 
664 # When an option value is fetched, the fact that it was used is 
665 # remembered. 
666 # Legal things to do:
667 # set a default value, then set a real value before the option is used.
668 # set a value, try to set a default, default silently fails.
669 # Illegal:
670 # use the value, then try to set the value
671
672 def newoption(name):
673         global global_options, global_options_by_order
674         o = getdict(global_options, name)
675         if (o):
676                 print "option %s already defined" % name
677                 sys.exit(1)
678         o = option(name)
679         setdict(global_options, name, o)
680         global_options_by_order.append(name)
681
682 def getoption(name, image):
683         """option must be declared before being used in a part
684         if we're not processing a part, then we must
685         be at the top level where all options are available
686         global global_uses_options, global_option_values"""
687         curpart = partstack.tos()
688         if (curpart):
689                 o = getdict(curpart.uses_options, name)
690         elif (alloptions):
691                 o = getdict(global_options, name)
692         else:
693                 o = getdict(global_uses_options, name)
694         if (o == 0 or not o.defined):
695                 error("Option %s undefined (missing use command?)" % name)
696                 return
697         v = 0
698         if (image):
699                 v = o.getvalue(image, image.getvalues())
700         if (v == 0):
701                 v = o.getvalue(image, global_option_values)
702         return v.contents()
703
704 def setoption(name, value):
705         global loc, global_options, global_option_values, curimage
706         curpart = partstack.tos()
707         if (curpart and curpart.type != 'mainboard'):
708                 fatal("Options may only be set in top-level and mainboard configuration files")
709         o = getdict(global_options, name)
710         if (o == 0):
711                 fatal("Attempt to set nonexistent option %s" % name)
712         v = option_value(value)
713         if (curimage):
714                 o.setvalue(v, curimage.getvalues(), loc)
715         else:
716                 o.setvalue(v, global_option_values, loc)
717
718 def setdefault(name, value):
719         global loc, global_options
720         o = getdict(global_options, name)
721         if (not o):
722                 return
723         if (o.default):
724                 print "setdefault: attempt to duplicate default for %s" % name
725                 return
726         v = option_value(value)
727         o.setdefault(v, loc)
728
729 def setnodefault(name):
730         global loc, global_options
731         o = getdict(global_options, name)
732         if (not o):
733                 return
734         if (o.default):
735                 print "setdefault: attempt to duplicate default for %s" % name
736                 return
737         o.setnodefault(loc)
738
739 def setcomment(name, value):
740         global loc, global_options
741         o = getdict(global_options, name)
742         if (not o):
743                 fatal("setcomment: %s not here" % name)
744         o.setcomment(value, loc)
745
746 def setexported(name):
747         global global_options
748         o = getdict(global_options, name)
749         if (not o):
750                 fatal("setexported: %s not here" % name)
751         o.setexported()
752
753 def setnoexport(name):
754         global global_options
755         o = getdict(global_options, name)
756         if (not o):
757                 fatal("setnoexport: %s not here" % name)
758         o.setnoexport()
759
760 def setexportable(name):
761         global global_options
762         o = getdict(global_options, name)
763         if (not o):
764                 fatal("setexportable: %s not here" % name)
765         o.setexportable()
766
767 def setformat(name, fmt):
768         global global_options
769         o = getdict(global_options, name)
770         if (not o):
771                 fatal("setformat: %s not here" % name)
772         o.setformat(fmt)
773
774 def getformated(name, image):
775         global global_options, global_option_values
776         o = getdict(global_options, name)
777         if (o == 0 or not o.defined):
778                 fatal( "Option %s undefined." % name)
779         v = 0
780         if (image):
781                 v = o.getvalue(image, image.getvalues())
782         if (v == 0):
783                 v = o.getvalue(image, global_option_values)
784         f = o.getformat()
785         return (f % v.contents())
786
787 def isexported(name):
788         global global_options
789         o = getdict(global_options, name)
790         if (o):
791                 return o.isexported()
792         return 0
793
794 #def isdefined(name, part):
795 #       global global_options
796 #       if (part):
797 #               o = getdict(part.uses_options, name)
798 #       else:
799 #               o = getdict(global_options, name)
800 #       if (o):
801 #               return o.isdefined()
802 #       return 0
803
804 def isset(name, part):
805         global global_uses_options
806         if (part):
807                 o = getdict(part.uses_options, name)
808         else:
809                 o = getdict(global_uses_options, name)
810         if (o):
811                 return o.isset()
812         return 0
813
814 #def isused(name, part):
815 #       global global_options
816 #       if (part):
817 #               o = getdict(part.uses_options, name)
818 #       else:
819 #               o = getdict(global_options, name)
820 #       if (o):
821 #               return o.isused()
822 #       return 0
823
824 def usesoption(name):
825         global global_options, global_uses_options
826         curpart = partstack.tos()
827         if (curpart):
828                 curpart.usesoption(name)
829                 return
830         o = getdict(global_options, name)
831         if (o == 0):
832                 fatal("Can't use undefined option %s" % name)
833         o.setused()
834         o1 = getdict(global_uses_options, name)
835         if (o1):
836                 return
837         setdict(global_uses_options, name, o)
838
839 def validdef(name, defval):
840         global global_options
841         o = getdict(global_options, name)
842         if (not o):
843                 fatal("validdef: %s not here" % name)
844         if ((defval & 1) != 1):
845             fatal("Must specify default value for option %s" % name)
846         if ((defval & 2) != 2):
847             fatal("Must specify export for option %s" % name)
848         if ((defval & 4) != 4):
849             fatal("Must specify comment for option %s" % name)
850
851 def loadoptions():
852         file = os.path.join('src', 'config', 'Options.lb')
853         optionsfile = os.path.join(treetop, file)
854         loc.push(file)
855         if (not parse('options', open(optionsfile, 'r').read())):
856                 fatal("Could not parse file")
857         loc.pop()
858
859 def addinit(path):
860         global curimage, dirstack
861         if (path[0] == '/'):
862                 curimage.setinitfile(treetop + '/src/' + path)
863         else:
864                 curimage.setinitfile(dirstack.tos() + '/' + path)
865         print "Adding init file: %s" % path
866
867 def addregister(code):
868         global partstack
869         curpart = partstack.tos()
870         curpart.addregister(code)
871
872 def addcrt0include(path):
873         """we do the crt0include as a dictionary, so that if needed we
874         can trace who added what when. Also it makes the keys
875         nice and unique."""
876         global curimage
877         curimage.addinitinclude(0, path)
878
879 def addinitinclude(str, path):
880         global curimage
881         curimage.addinitinclude(dequote(str), path)
882
883 def addldscript(path):
884         global curimage, dirstack
885         curdir = dirstack.tos()
886         if (path[0] == '/'):
887                 fullpath =  treetop + '/src/' + path
888         else:
889                 fullpath = curdir + '/' + path
890         debug.info(debug.statement, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path))
891         curimage.addldscript(fullpath)
892
893 def payload(path):
894         global curimage
895         curimage.setpayload(path)
896 #       adduserdefine("PAYLOAD:=%s"%path)
897 #       addrule('payload')
898 #       adddep('payload', path)
899 #       addaction('payload', 'cp $< $@')
900
901 def startromimage(name):
902         global romimages, curimage, target_dir, target_name
903         print "Configuring ROMIMAGE %s" % name
904         o = getdict(romimages, name)
905         if (o):
906                 fatal("romimage %s previously defined" % name)
907         curimage = romimage(name)
908         curimage.settargetdir(os.path.join(target_dir, name))
909         #o = partobj(curimage, target_dir, 0, 'board', target_name)
910         #curimage.setroot(o)
911         setdict(romimages, name, curimage)
912
913 def endromimage():
914         global curimage
915         print "End ROMIMAGE"
916         curimage = 0
917         #curpart = 0
918
919 def mainboard(path):
920         full_path = os.path.join(treetop, 'src', 'mainboard', path)
921         setoption('MAINBOARD', full_path)
922         vendor = re.sub("/.*", "", path)
923         part_number = re.sub("[^/]*/", "", path)
924         setoption('MAINBOARD_VENDOR', vendor)
925         setoption('MAINBOARD_PART_NUMBER', part_number)
926         dodir('/config', 'Config.lb')
927         part('mainboard', path, 'Config.lb')
928         curimage.setroot(partstack.tos())
929         partpop()
930
931 def addbuildrom(size, roms):
932         global buildroms
933         print "Build ROM size %d" % size
934         b = buildrom(size, roms)
935         buildroms.append(b)
936
937 def addinitobject(object_name):
938         global curimage
939         curimage.addinitobjectrule(object_name)
940
941 def addobject(object_name):
942         global curimage
943         curimage.addobjectrule(object_name)
944
945 def adddriver(driver_name):
946         global curimage
947         curimage.adddriverrule(driver_name)
948
949 def target(name):
950         global target_dir, target_name
951         print "Configuring TARGET %s" % name
952         target_name = name
953         target_dir = os.path.join(os.path.dirname(loc.file()), name)
954         if not os.path.isdir(target_dir):
955                 print "Creating directory %s" % target_dir
956                 os.makedirs(target_dir)
957         print "Will place Makefile, crt0.S, etc. in %s" % target_dir
958
959
960 def part(name, path, file):
961         global curimage, dirstack, partstack
962         partdir = os.path.join(name, path)
963         srcdir = os.path.join(treetop, 'src')
964         fulldir = os.path.join(srcdir, partdir)
965         newpart = partobj(curimage, fulldir, partstack.tos(), name, path)
966         print "Configuring PART %s, path %s" % (name, path)
967         partstack.push(newpart)
968         dirstack.push(fulldir)
969         doconfigfile(srcdir, partdir, file)
970
971 def partpop():
972         global dirstack, partstack
973         curpart = partstack.pop()
974         if (curpart == 0):
975                 fatal("Trying to pop non-existent part")
976         print "End PART %s" % curpart.type
977         # Warn if options are used without being set in this part
978         for i in curpart.uses_options.keys():
979                 if (not isset(i, curpart)):
980                         print "WARNING: Option %s using default value %s" % (i, getformated(i, curpart.image))
981         dirstack.pop()
982
983 def dodir(path, file):
984         """dodir is like part but there is no new part"""
985         global dirstack
986         # if the first char is '/', it is relative to treetop, 
987         # else relative to curdir
988         # os.path.join screws up if the name starts with '/', sigh.
989         print "Configuring DIR %s" % os.path.join(path, file)
990         if (path[0] == '/'):
991                 fullpath = os.path.join(treetop, 'src')
992                 path = re.sub('^/*', '', path)
993         else:
994                 fullpath = dirstack.tos()
995         debug.info(debug.statement, "DODIR: path %s, fullpath %s" % (path, fullpath))
996         dirstack.push(os.path.join(fullpath, path))
997         doconfigfile(fullpath, path, file)
998         dirstack.pop()
999
1000 def lookup(name):
1001         global curimage
1002         v = getoption(name, curimage)
1003         exitiferrors()
1004         return v
1005
1006 def addrule(id):
1007         global curimage
1008         curimage.addmakerule(id)
1009         
1010 def adduserdefine(str):
1011         global curimage
1012         curimage.adduserdefine(str)
1013
1014 def addaction(id, str):
1015         global curimage
1016         curimage.addmakeaction(id, str)
1017
1018 def adddep(id, str):
1019         global curimage
1020         curimage.addmakedepend(id, str)
1021
1022 def set_arch(my_arch):
1023         """arch is 'different' ... darn it."""
1024         global curimage
1025         curimage.setarch(my_arch)
1026         setoption('ARCH', my_arch)
1027         part('arch', my_arch, 'Config.lb')
1028
1029 def doconfigfile(path, confdir, file):
1030         rname = os.path.join(confdir, file)
1031         loc.push(rname)
1032         fullpath = os.path.join(path, rname)
1033         if (not parse('cfgfile', open(fullpath, 'r').read())):
1034                 fatal("Could not parse file")
1035         exitiferrors()
1036         loc.pop()
1037
1038 #=============================================================================
1039 #               MISC FUNCTIONS
1040 #=============================================================================
1041 def ternary(val, yes, no):
1042         debug.info(debug.statement, "ternary %s" % expr)
1043         debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no))
1044         if (val == 0):
1045                 debug.info(debug.statement, "Ternary returns %d" % yes)
1046                 return yes
1047         else:
1048                 debug.info(debug.statement, "Ternary returns %d" % no)
1049                 return no
1050
1051 def tohex(name):
1052         """atoi is in the python library, but not strtol? Weird!"""
1053         return eval('int(%s)' % name)
1054
1055 def IsInt( str ):
1056         """ Is the given string an integer?"""
1057         try:
1058                 num = int(str)
1059                 return 1
1060         except ValueError:
1061                 return 0
1062
1063 def dequote(str):
1064         a = re.sub("^\"", "", str)
1065         a = re.sub("\"$", "", a)
1066         # highly un-intuitive, need four \!
1067         a = re.sub("\\\\\"", "\"", a)
1068         return a
1069
1070 def flatten_name(str):
1071         a = re.sub("/", "_", str)
1072         return a
1073
1074 def topify(path):
1075         """If the first part of <path> matches treetop, replace 
1076         that part with $(TOP)"""
1077         if path[0:len(treetop)] == treetop:
1078                 path = path[len(treetop):len(path)]
1079                 if (path[0:1] == "/"):
1080                         path = path[1:len(path)]
1081                 path = "$(TOP)/" + path
1082         return path
1083
1084 %%
1085 # to make if work without 2 passses, we use an old hack from SIMD, the 
1086 # context bit. If the bit is 1, then ops get done, otherwise
1087 # ops don't get done. From the top level, context is always
1088 # 1. In an if, context depends on eval of the if condition
1089
1090 parser Config:
1091     ignore:                     r'\s+'
1092     ignore:                     "#.*?\r?\n"
1093
1094     # less general tokens should come first, otherwise they get matched
1095     # by the re's
1096     token ACTION:               'action'
1097     token ADDACTION:            'addaction'
1098     token ALWAYS:               'always'
1099     token ARCH:                 'arch'
1100     token BUILDROM:             'buildrom'
1101     token COMMENT:              'comment'
1102     token CPU:                  'cpu'
1103     token DEFAULT:              'default'
1104     token DEFINE:               'define'
1105     token DEPENDS:              'depends'
1106     token DIR:                  'dir'
1107     token DRIVER:               'driver'
1108     token ELSE:                 'else'
1109     token END:                  'end'
1110     token EOF:                  '$'
1111     token EQ:                   '='
1112     token EXPORT:               'export'
1113     token FORMAT:               'format'
1114     token IF:                   'if'
1115     token INIT:                 'init'
1116     token INITOBJECT:           'initobject'
1117     token INITINCLUDE:          'initinclude'
1118     token LDSCRIPT:             'ldscript'
1119     token LOADOPTIONS:          'loadoptions'
1120     token MAINBOARD:            'mainboard'
1121     token MAINBOARDINIT:        'mainboardinit'
1122     token MAKEDEFINE:           'makedefine'
1123     token MAKERULE:             'makerule'
1124     token NEVER:                'never'
1125     token NONE:                 'none'
1126     token NORTHBRIDGE:          'northbridge'
1127     token OBJECT:               'object'
1128     token OPTION:               'option'
1129     token PAYLOAD:              'payload'
1130     token PMC:                  'pmc'
1131     token PRINT:                'print'
1132     token REGISTER:             'register'
1133     token ROMIMAGE:             'romimage'
1134     token SOUTHBRIDGE:          'southbridge'
1135     token SUPERIO:              'superio'
1136     token TARGET:               'target'
1137     token USED:                 'used'
1138     token USES:                 'uses'
1139     token NUM:                  r'[0-9]+'
1140     token XNUM:                 r'0x[0-9a-fA-F]+'
1141     # Why is path separate? Because paths to resources have to at least
1142     # have a slash, we thinks
1143     token PATH:                 r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+'
1144     # Dir's on the other hand are abitrary
1145     # this may all be stupid.
1146     token DIRPATH:              r'[-a-zA-Z0-9_$()./]+'
1147     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
1148     token DELEXPR:              r'{([^}]+|\\.)*}'
1149     token STR:                  r'"([^\\"]+|\\.)*"'
1150     token RAWTEXT:              r'.*'
1151
1152     rule expr:          logical                 {{ l = logical }}
1153                         ( "&&" logical          {{ l = l and logical }}
1154                         | "||"  logical         {{ l = l or logical }}
1155                         )*                      {{ return l }}
1156
1157     rule logical:       factor                  {{ n = factor }}
1158                         ( "[+]" factor          {{ n = n+factor }}
1159                         | "-"  factor           {{ n = n-factor }}
1160                         )*                      {{ return n }}
1161
1162     rule factor:        term                    {{ v = term }}
1163                         ( "[*]" term            {{ v = v*term }}
1164                         | "/"  term             {{ v = v/term }}
1165                         | "<<"  term            {{ v = v << term }}
1166                         | ">=" term             {{ v = (v < term)}}
1167                         )*                      {{ return v }}
1168
1169     # A term is a number, variable, or an expression surrounded by parentheses
1170     rule term:          NUM                     {{ return atoi(NUM) }}
1171                 |       XNUM                    {{ return tohex(XNUM) }}
1172                 |       ID                      {{ return lookup(ID) }}
1173                 |       unop                    {{ return unop }}
1174                 |       "\\(" expr "\\)"        {{ return expr }}
1175
1176     rule unop:          "!" expr                {{ return not(expr) }}
1177
1178     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
1179
1180     rule northbridge<<C>>:
1181                         NORTHBRIDGE PATH        {{ if (C): part('northbridge', PATH, 'Config.lb') }}
1182                         partend<<C>>
1183
1184     rule superio<<C>>:  SUPERIO PATH            {{ if (C): part('superio', PATH, 'Config.lb') }}
1185                         partend<<C>>
1186
1187     rule cpu<<C>>:      CPU ID                  {{ if (C): part('cpu', ID, 'Config.lb') }}
1188                         partend<<C>>
1189
1190     rule pmc<<C>>:      PMC PATH                {{ if (C): part('pmc', PATH, 'Config.lb') }}
1191                         partend<<C>>
1192
1193     rule arch<<C>>:     ARCH ID                 {{ if (C): set_arch(ID) }}
1194                         partend<<C>>
1195
1196     rule southbridge<<C>>:
1197                         SOUTHBRIDGE PATH        {{ if (C): part('southbridge', PATH, 'Config.lb')}}
1198                         partend<<C>>
1199
1200     rule mainboardinit<<C>>:
1201                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1202
1203     rule initinclude<<C>>: 
1204                         INITINCLUDE 
1205                         STR 
1206                         DIRPATH                 {{ if (C): addinitinclude(STR, DIRPATH)}}
1207
1208     rule initobject<<C>>:
1209                         INITOBJECT DIRPATH      {{ if (C): addinitobject(DIRPATH)}}
1210
1211     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1212
1213     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1214
1215     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1216
1217     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1218
1219     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1220                         (stmt<<C and c>>)* 
1221                         [ ELSE (stmt<<C and not c>>)* ]
1222                         END
1223
1224     rule depsacts<<ID, C>>:
1225                         ( DEPENDS STR           {{ if (C): adddep(ID, STR) }}
1226                         | ACTION STR            {{ if (C): addaction(ID, STR) }}
1227                         )*
1228
1229     rule makerule<<C>>: MAKERULE DIRPATH        {{ if (C): addrule(DIRPATH) }} 
1230                         depsacts<<DIRPATH, C>> 
1231                         END
1232
1233     rule makedefine<<C>>:
1234                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1235
1236     rule addaction<<C>>:
1237                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1238
1239     rule init<<C>>:     INIT DIRPATH            {{ if (C): addinit(DIRPATH) }}
1240
1241     rule register<<C>>: REGISTER STR            {{ if (C): addregister(STR) }}
1242
1243     rule prtval:        expr                    {{ return str(expr) }}
1244                 |       STR                     {{ return STR }}
1245
1246     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
1247                         ( "," prtval            {{ el = el + "," + prtval }}
1248                         )*                      {{ return el + ")" }}   
1249
1250     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
1251                         [ "," prtlist           {{ val = val + prtlist }}
1252                         ]                       {{ if (C): print eval(val) }}
1253
1254     rule stmt<<C>>:     arch<<C>>               {{ return arch}}
1255                 |       addaction<<C>>          {{ return addaction }}
1256                 |       cpu<<C>>                {{ return cpu}}
1257                 |       dir<<C>>                {{ return dir}}
1258                 |       driver<<C>>             {{ return driver }}
1259                 |       iif<<C>>                {{ return iif }}
1260                 |       init<<C>>               {{ return init }}
1261                 |       initinclude<<C>>        {{ return initinclude }}
1262                 |       initobject<<C>>         {{ return initobject }}
1263                 |       ldscript<<C>>           {{ return ldscript}}
1264                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1265                 |       makedefine<<C>>         {{ return makedefine }}
1266                 |       makerule<<C>>           {{ return makerule }}
1267                 |       northbridge<<C>>        {{ return northbridge }}
1268                 |       object<<C>>             {{ return object }}
1269                 |       option<<C>>             {{ return option }}
1270                 |       pmc<<C>>                {{ return pmc}}
1271                 |       prtstmt<<C>>            {{ return prtstmt}}
1272                 |       register<<C>>           {{ return register}}
1273                 |       southbridge<<C>>        {{ return southbridge }}
1274                 |       superio<<C>>            {{ return superio }}
1275
1276     # ENTRY for parsing Config.lb file
1277     rule cfgfile:       (uses<<1>>)* 
1278                         (stmt<<1>>)*
1279                         EOF                     {{ return 1 }}
1280
1281     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1282
1283     rule uses<<C>>:     USES (usesid<<C>>)+
1284
1285     rule value:         STR                     {{ return dequote(STR) }} 
1286                 |       expr                    {{ return expr }}
1287                 |       DELEXPR                 {{ return DELEXPR }}
1288
1289     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoption(ID, value) }}
1290
1291     rule opif<<C>>:     IF ID                   {{ c = lookup(ID) }}
1292                         (opstmt<<C and c>>)* 
1293                         [ ELSE (opstmt<<C and not c>>)* ] 
1294                         END
1295
1296     rule opstmt<<C>>:   option<<C>>
1297                 |       opif<<C>>
1298                 |       prtstmt<<C>>
1299
1300     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1301
1302     rule mainboard<<C>>:
1303                         MAINBOARD PATH          {{ if (C): mainboard(PATH) }}
1304
1305     rule romif<<C>>:    IF ID                   {{ c = lookup(ID) }}
1306                         (romstmt<<C and c>>)* 
1307                         [ ELSE (romstmt<<C and not c>>)* ]
1308                         END
1309
1310     rule romstmt<<C>>:  romif<<C>>
1311                 |       option<<C>>
1312                 |       mainboard<<C>>
1313                 |       payload<<C>>
1314
1315     rule romimage:      ROMIMAGE STR            {{ startromimage(dequote(STR)) }}
1316                         (romstmt<<1>>)*
1317                         END                     {{ endromimage() }}
1318
1319     rule roms:          STR                     {{ s = '(' + STR }}
1320                         ( STR                   {{ s = s + "," + STR }}
1321                         )*                      {{ return eval(s + ')') }}
1322
1323     rule buildrom:      BUILDROM expr roms      {{ addbuildrom(expr, roms) }}
1324
1325     rule romstmts:      romimage 
1326                 |       buildrom
1327                 |       opstmt<<1>>
1328
1329     # ENTRY for parsing root part
1330     rule board:         LOADOPTIONS             {{ loadoptions() }}
1331                         TARGET DIRPATH          {{ target(DIRPATH) }}
1332                         (uses<<1>>)*
1333                         (romstmts)*             
1334                         EOF                     {{ return 1 }}
1335
1336     # ENTRY for parsing a delayed value
1337     rule delexpr:       "{" expr "}" EOF        {{ return expr }}
1338
1339     rule defstmts<<ID>>:                        {{ d = 0 }}
1340                         ( DEFAULT
1341                           ( value               {{ setdefault(ID, value) }}
1342                           | NONE                {{ setnodefault(ID) }}
1343                           )                     {{ d = d | 1 }}
1344                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1345                         | EXPORT 
1346                           ( ALWAYS              {{ setexported(ID) }}
1347                           | USED                {{ setexportable(ID) }}
1348                           | NEVER               {{ setnoexport(ID) }}
1349                           )                     {{ d = d | 2 }}
1350                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1351                         )+                      {{ return d }}
1352                 
1353     rule define:        DEFINE ID               {{ newoption(ID) }}
1354                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
1355
1356     # ENTRY for parsing Options.lb file
1357     rule options:       (define)* EOF           {{ return 1 }}
1358 %%
1359
1360 #=============================================================================
1361 #               FILE OUTPUT 
1362 #=============================================================================
1363 def writemakefileheader(file, fname):
1364         file.write("# File: %s\n" % fname)
1365         file.write("# This file was generated by '%s %s %s'\n\n"
1366                 % (sys.argv[0], sys.argv[1], sys.argv[2]))
1367
1368 def writemakefilesettings(path):
1369         global treetop, target_dir
1370         # Write Makefile.settings to seperate the settings
1371         # from the actual makefile creation
1372         # In practice you need to rerun NLBConfig.py to change
1373         # these but in theory you shouldn't need to.
1374
1375         filename = os.path.join(path, "Makefile.settings")
1376         print "Creating", filename
1377         file = open(filename, 'w+')
1378         writemakefileheader(file, filename)
1379         file.write("TOP:=%s\n" % (treetop))
1380         file.write("TARGET_DIR:=%s\n" % target_dir)
1381 #       for i in global_options_by_order:
1382 #               if (isexported(i, 0)):
1383 #                       file.write("export %s:=%s\n" % (i, getformated(i, 0)))
1384 #       file.write("export VARIABLES := ")
1385 #       for i in global_options.keys():
1386 #               if (isexported(i, 0)):
1387 #                       file.write("%s " % i)
1388         file.write("\n")
1389         file.close()
1390
1391 def writeimagesettings(image):
1392         global treetop
1393         global global_options_by_order
1394         # Write Makefile.settings to seperate the settings
1395         # from the actual makefile creation
1396         # In practice you need to rerun NLBConfig.py to change
1397         # these but in theory you shouldn't need to.
1398
1399         filename = os.path.join(image.gettargetdir(), "Makefile.settings")
1400         print "Creating", filename
1401         file = open(filename, 'w+')
1402         writemakefileheader(file, filename)
1403         file.write("TOP:=%s\n" % (treetop))
1404         file.write("TARGET_DIR:=%s\n" % (image.gettargetdir()))
1405         for i in global_options_by_order:
1406                 if (isexported(i)):
1407                         file.write("export %s:=%s\n" % (i, getformated(i, image)))
1408         file.write("export VARIABLES := ")
1409         for i in global_options_by_order:
1410                 if (isexported(i)):
1411                         file.write("%s " % i)
1412         file.write("\n")
1413         file.close()
1414
1415 # write the romimage makefile
1416 # let's try the Makefile
1417 # first, dump all the -D stuff
1418
1419 def writeimagemakefile(image):
1420         makefilepath = os.path.join(image.gettargetdir(), "Makefile")
1421         print "Creating", makefilepath
1422         file = open(makefilepath, 'w+')
1423         writemakefileheader(file, makefilepath)
1424
1425         #file.write("include cpuflags\n")
1426         # Putting "include cpuflags" in the Makefile has the problem that the
1427         # cpuflags file would be generated _after_ we want to include it.
1428         # Instead, let make do the work of computing CPUFLAGS:
1429         file.write("# Get the value of TOP, VARIABLES, and several other variables.\n")
1430         file.write("include Makefile.settings\n\n")
1431         file.write("# Function to create an item like -Di586 or -DMAX_CPUS='1' or -Ui686\n")
1432         file.write("D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)\n\n")
1433         file.write("# Compute the value of CPUFLAGS here during make's first pass.\n")
1434         file.write("CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))\n\n")
1435
1436         for i in image.getuserdefines():
1437                 file.write("%s\n" %i)
1438         file.write("\n")
1439
1440         # main rule
1441         file.write("all: linuxbios.rom")
1442         # print out all the object dependencies
1443         file.write("\n# object dependencies (objectrules:)\n")
1444         file.write("INIT-OBJECTS :=\n")
1445         file.write("OBJECTS :=\n")
1446         file.write("DRIVER :=\n")
1447         file.write("\nSOURCES :=\n")
1448         for irule, init in image.getinitobjectrules().items():
1449                 i_name = init[0]
1450                 i_source = init[1]
1451                 file.write("INIT-OBJECTS += %s\n" % (i_name))
1452                 file.write("SOURCES += %s\n" % (i_source))
1453
1454         for objrule, obj in image.getobjectrules().items():
1455                 obj_name = obj[0]
1456                 obj_source = obj[1]
1457                 file.write("OBJECTS += %s\n" % (obj_name))
1458                 file.write("SOURCES += %s\n" % (obj_source))
1459
1460         # for chip_target.c
1461         file.write("OBJECTS += chip_%s.o\n" % target_name)
1462         file.write("SOURCES += chip_%s.c\n" % target_name)
1463
1464         for driverrule, driver in image.getdriverrules().items():
1465                 obj_name = driver[0]
1466                 obj_source = driver[1]
1467                 file.write("DRIVER += %s\n" % (obj_name))
1468                 file.write("SOURCES += %s\n" % (obj_source))
1469
1470         # Print out all ldscript.ld dependencies.
1471         file.write("\n# ldscript.ld dependencies:\n")
1472         file.write("LDSUBSCRIPTS-1 := \n" )
1473         for script in image.getldscripts():
1474                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
1475
1476         # Print out the dependencies for crt0_includes.h
1477         file.write("\n# Dependencies for crt0_includes.h\n")
1478         file.write("CRT0_INCLUDES:=\n")
1479         for inc in image.getinitincludes():
1480                 if (local_path.match(inc)):
1481                         file.write("CRT0_INCLUDES += %s\n" % inc)
1482                 else:
1483                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % inc)
1484
1485         # Print out the user defines.
1486         file.write("\n# userdefines:\n")
1487         #for udef in image.userdefines:
1488                 #file.write("%s\n" % udef)
1489                 
1490         # Print out the base rules.
1491         # Need to have a rule that counts on 'all'.
1492         file.write("\n# mainrulelist:")
1493         #file.write("\nmainrule: %s\n" % image.mainrulelist)
1494
1495         # Print out any user rules.
1496         file.write("\n# From makerule or docipl commands:\n")
1497         # Old way (hash order): for target in makebaserules.keys():
1498         # New way (config file order):
1499         #for target in image.makerule_targets:
1500                 #image.makebaserules[target].write(file)
1501
1502         file.write("\n# objectrules:\n")
1503         for objrule, obj in image.getobjectrules().items():
1504                 source = topify(obj[1])
1505                 file.write("%s: %s\n" % (obj[0], source))
1506                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1507                 #file.write("%s\n" % objrule[2])
1508
1509         for driverrule, driver in image.getdriverrules().items():
1510                 source = topify(driver[1])
1511                 file.write("%s: %s\n" % (driver[0], source))
1512                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1513                 #file.write("%s\n" % objrule[2])
1514
1515         # special rule for chip_target.c
1516         file.write("chip_%s.o: chip_%s.c\n" % (target_name, target_name))
1517         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1518
1519         # Print out the rules that will make cause the files
1520         # generated by NLBConfig.py to be remade if any dependencies change.
1521
1522         file.write("\n# Remember the automatically generated files\n")
1523         file.write("GENERATED:=\n")
1524         for genfile in ['Makefile',
1525                         'nsuperio.c',
1526                         'chip_%s.c' % target_name, 
1527                         'LinuxBIOSDoc.config' ]:
1528                 file.write("GENERATED += %s\n" % genfile)
1529         file.write("GENERATED += %s\n" % image.getincludefilename())
1530
1531         #file.write("\n# Remake Makefile (and the other files generated by\n")
1532         #file.write("# NLBConfig.py) if any config dependencies change.\n")
1533
1534         #for cfile in image.config_file_list:
1535         #       file.write("$(GENERATED): %s\n" % topify(cfile))
1536
1537         #for depfile in [ '%s' % top_config_file,    # This a duplicate, remove?
1538         #               '$(TOP)/util/config/NLBConfig.py',
1539         #               '$(TOP)/src/arch/$(ARCH)/config/make.base' ]:
1540         #       file.write("$(GENERATED): %s\n" % depfile)
1541
1542         #file.write("$(GENERATED):\n")
1543         #file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n"
1544         #               % top_config_file)
1545
1546         keys = image.getroot().uses_options.keys()
1547         keys.sort()
1548         file.write("\necho:\n")
1549         for key in keys:
1550                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
1551
1552         for i, m in image.getmakerules().items():
1553                 file.write("%s: " %i)
1554                 for i in m.dependency:
1555                         file.write("%s " % i)
1556                 file.write("\n")
1557                 for i in m.actions:
1558                         file.write("\t%s\n" % i)
1559         file.close()
1560
1561 #
1562 def writemakefile(path):
1563         makefilepath = os.path.join(path, "Makefile")
1564         print "Creating", makefilepath
1565         file = open(makefilepath, 'w+')
1566         writemakefileheader(file, makefilepath)
1567
1568         # main rule
1569         file.write("all: ")
1570         for i in romimages.keys():
1571                 file.write("%s-rom " % i)
1572         file.write("\n\n")
1573         for i, o in romimages.items():
1574                 file.write("%s-rom:\n" % o.getname())
1575                 file.write("\tif (cd %s; \\\n" % o.getname())
1576                 file.write("\t\tmake linuxbios.rom)\\\n");
1577                 file.write("\tthen true; else exit 1; fi;\n\n")
1578         file.close()
1579
1580 def writeinitincludes(image):
1581         global include_pattern
1582         filepath = os.path.join(image.gettargetdir(), image.getincludefilename())
1583         print "Creating", filepath
1584         outfile = open(filepath, 'w+')
1585         if (image.newformat()):
1586                 infile = open(image.getinitfile(), 'r')
1587
1588                 line = infile.readline()
1589                 while (line):
1590                         p = include_pattern.match(line)
1591                         if (p):
1592                                 for i in image.getinitincludes():
1593                                         inc = image.getinitinclude(i)
1594                                         if (inc.getstring() == p.group(1)):
1595                                                 outfile.write("#include \"%s\"\n" % inc.getpath())
1596                         else:
1597                                 outfile.write(line);
1598                         line = infile.readline()
1599
1600                 infile.close()
1601         else:
1602                 for i in image.getinitincludes():
1603                         outfile.write("#include <%s>\n" % i)
1604         outfile.close()
1605
1606 def writeldoptions(image):
1607         # Write Makefile.settings to seperate the settings
1608         # from the actual makefile creation
1609         # In practice you need to rerun NLBConfig.py to change
1610         # these but in theory you shouldn't need to.
1611
1612         filename = os.path.join(image.gettargetdir(), "ldoptions")
1613         print "Creating", filename
1614         file = open(filename, 'w+')
1615         for i in global_options.keys():
1616                 if (isexported(i) and IsInt(getoption(i, image))):
1617                         file.write("%s = %s;\n" % (i, getformated(i, image)))
1618         file.close()
1619
1620 def dumptree(part, lvl):
1621         debug.info(debug.dumptree, "DUMPTREE ME is")
1622         part.dumpme(lvl)
1623         # dump the siblings -- actually are there any? not sure
1624         # siblings are:
1625         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
1626         kid = part.siblings
1627         while (kid):
1628                 kid.dumpme(lvl)
1629                 kid = kid.siblings
1630         # dump the kids
1631         debug.info(debug.dumptree, "DUMPTREE KIDS are")
1632         #for kid in part.children:
1633         if (part.children):
1634                 dumptree(part.children, lvl+1)
1635         debug.info(debug.dumptree, "DONE DUMPTREE")
1636
1637 def writecode(image):
1638         filename = os.path.join(img_dir, "chip_%s.c" % target_name)
1639         print "Creating", filename
1640         file = open(filename, 'w+')
1641         # gen all the forward references
1642
1643         i = 0
1644         file.write("#include <device/chip.h>\n")
1645         file.write("struct chip ")
1646         while (i <= image.numparts()):
1647                 if (i):
1648                         file.write(", dev%d"% i)
1649                 else:
1650                         file.write("root")
1651                 i = i + 1
1652         file.write(";\n")
1653         gencode(image.getroot(), file)
1654         file.close()
1655
1656 def gencode(part, file):
1657         debug.info(debug.gencode, "GENCODE ME is")
1658         part.gencode(file)
1659         # dump the siblings -- actually are there any? not sure
1660         debug.info(debug.gencode, "GENCODE SIBLINGS are")
1661         kid = part.siblings
1662         while (kid):
1663                 kid.gencode(file)
1664                 kid = kid.siblings
1665         # now dump the children 
1666         debug.info(debug.gencode, "GENCODE KIDS are")
1667         if (part.children):
1668                 gencode(part.children, file)
1669         kid = part.siblings
1670         while (kid):
1671                 if (kid.children):
1672                         gencode(kid.children, file)
1673                 kid = kid.siblings
1674         debug.info(debug.gencode, "DONE GENCODE")
1675
1676 def verifyparse(image):
1677         """Add any run-time checks to verify that parsing the configuration
1678         was successful"""
1679         if (image.newformat() and image.getinitfile() == ''):
1680                 fatal("An init file must be specified")
1681
1682 #=============================================================================
1683 #               MAIN PROGRAM
1684 #=============================================================================
1685 if __name__=='__main__':
1686         from sys import argv
1687         if (len(argv) < 3):
1688                 print 'Args: <file> <path to linuxbios>'
1689                 sys.exit(1)
1690
1691         top_config_file = os.path.abspath(sys.argv[1])
1692
1693         treetop = os.path.abspath(sys.argv[2])
1694
1695         # Now read in the customizing script...
1696         loc.push(argv[1])
1697         if (not parse('board', open(argv[1], 'r').read())):
1698                 fatal("Could not parse file")
1699         loc.pop()
1700
1701         for r in romimages.keys():
1702                 verifyparse(getdict(romimages, r))
1703
1704         # no longer need to check if an options has been used
1705         alloptions = 1
1706
1707         for image_name, image in romimages.items():
1708                 if (debug.level(debug.dumptree)):
1709                         debug.info(debug.dumptree, "DEVICE TREE:")
1710                         dumptree(image.getroot(), 0)
1711
1712                 img_dir = image.gettargetdir()
1713                 if not os.path.isdir(img_dir):
1714                         print "Creating directory %s" % img_dir
1715                         os.makedirs(img_dir)
1716
1717                 # crt0 includes
1718                 if (debug.level(debug.dump)):
1719                         for i in image.getinitincludes():
1720                                 debug.info(debug.dump, "crt0include file %s" % i)
1721                         for i in image.getdriverrules().keys():
1722                                 debug.info(debug.dump, "driver file %s" % i)
1723                         for i in image.getldscripts():
1724                                 debug.info(debug.dump, "ldscript file %s" % i)
1725                         for i, m in image.getmakerules().items():
1726                                 debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions))
1727
1728                 writecode(image)
1729                 writeimagesettings(image)
1730                 writeinitincludes(image)
1731                 writeimagemakefile(image)
1732                 writeldoptions(image)
1733
1734         writemakefilesettings(target_dir)
1735         writemakefile(target_dir)
1736
1737         sys.exit(0)