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