Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-03 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 18:28 +1000, Benjamin Herrenschmidt wrote:
 Here is the kernel patch. It applies on top of the various prom_init.c
 bug fixes that I already posted today on the linuxppc-dev 
 linuxppc64-dev lists (those will be in the next -mm and maybe in
 2.6.12).
 
 This patch is intended to hit upstream by 2.6.13

Ok, the patch I posted with version 0.4 implementing version 0x10 of the
format was broken, here is a fixed version against current linus git
as of today:

Index: linux-work/arch/ppc64/kernel/prom_init.c
===
--- linux-work.orig/arch/ppc64/kernel/prom_init.c   2005-06-03 
16:52:28.0 +1000
+++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-03 16:58:01.0 
+1000
@@ -1534,7 +1534,8 @@
  */
 #define MAX_PROPERTY_NAME 64
 
-static void __init scan_dt_build_strings(phandle node, unsigned long 
*mem_start,
+static void __init scan_dt_build_strings(phandle node,
+unsigned long *mem_start,
 unsigned long *mem_end)
 {
unsigned long offset = reloc_offset();
@@ -1547,16 +1548,21 @@
/* get and store all property names */
prev_name = RELOC();
for (;;) {
-   int rc;
-
/* 64 is max len of name including nul. */
namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
-   rc = call_prom(nextprop, 3, 1, node, prev_name, namep);
-   if (rc != 1) {
+   if (call_prom(nextprop, 3, 1, node, prev_name, namep) != 1) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
}
+
+   /* skip name */
+   if (strcmp(namep, RELOC(name)) == 0) {
+   *mem_start = (unsigned long)namep;
+   prev_name = RELOC(name);
+   continue;
+   }
+   /* get/create string entry */
soff = dt_find_string(namep);
if (soff != 0) {
*mem_start = (unsigned long)namep;
@@ -1571,7 +1577,7 @@
 
/* do all our children */
child = call_prom(child, 1, 1, node);
-   while (child != (phandle)0) {
+   while (child != 0) {
scan_dt_build_strings(child, mem_start, mem_end);
child = call_prom(peer, 1, 1, child);
}
@@ -1580,16 +1586,13 @@
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
 {
-   int l, align;
phandle child;
-   char *namep, *prev_name, *sstart, *p, *ep;
+   char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
-   char pname[MAX_PROPERTY_NAME];
-   char *path;
-
-   path = RELOC(prom_scratch);
+   static char pname[MAX_PROPERTY_NAME];
+   int l;
 
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -1599,23 +1602,33 @@
  namep, *mem_end - *mem_start);
if (l = 0) {
/* Didn't fit?  Get more room. */
-   if (l+1  *mem_end - *mem_start) {
+   if ((l+1)  (*mem_end - *mem_start)) {
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom(package-to-path, 3, 1, node, namep, l);
}
namep[l] = '\0';
+
/* Fixup an Apple bug where they have bogus \0 chars in the
 * middle of the path in some properties
 */
for (p = namep, ep = namep + l; p  ep; p++)
if (*p == '\0') {
memmove(p, p+1, ep - p);
-   ep--; l--;
+   ep--; l--; p--;
}
-   *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 
1, 4);
+
+   /* now try to extract the unit name in that mess */
+   for (p = namep, lp = NULL; *p; p++)
+   if (*p == '/')
+   lp = p + 1;
+   if (lp != NULL)
+   memmove(namep, lp, strlen(lp) + 1);
+   *mem_start = _ALIGN(((unsigned long) namep) +
+   strlen(namep) + 1, 4);
}
 
/* get it again for debugging */
+   path = RELOC(prom_scratch);
memset(path, 0, PROM_SCRATCH_SIZE);
call_prom(package-to-path, 3, 1, node, path, PROM_SCRATCH_SIZE-1);
 
@@ -1623,23 +1636,27 @@
prev_name = RELOC();
sstart = (char *)RELOC(dt_string_start);
for (;;) {
-   int rc;
-
-   rc = call_prom(nextprop, 3, 1, node, prev_name, pname);
-  

Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-03 Thread David Gibson
On Thu, Jun 02, 2005 at 05:09:18PM +1000, David Gibson wrote:
 On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote:
  DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
  
  Here's the fourth version of my document along with new kernel patches
  for the new improved flattened format, and the first release of the
  device-tree compiler tool. The patches will be posted as a reply to
  this email. The compiler, dtc, can be downloaded, the URL is in the
  document.
 
 [snip]
 
  IV - dtc, the device tree compiler
  
 
  
  dtc source code can be found at
  http://ozlabs.org/~dgibson/dtc/dtc.tar.gz
 
 I've just updated the dtc tarball with a new version.  Notable
 changes:
   - Corrected comment parsing
   - Corrected handling of #address-cells, #size-cells properties
   - Input from device tree blobs should actually work now
   - Corrected autogeneration of name properties in blob/asm
 output version  0x10
   - Added a TODO list

And yet another.  Notable changes:
- Basic generation of the reserve map in blob output, use -R
  command line option to leave space for a number of reserve
  map entries to be filled in by bootloader.
- Rewrite blob and assembler output to better share code, and
  produce more readable assembler output.


-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/people/dgibson



Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-02 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 11:58 -0500, Jon Loeliger wrote:
 On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
  Here's the fourth version of my document along with new kernel patches
  for the new improved flattened format, and the first release of the
  device-tree compiler tool. The patches will be posted as a reply to
  this email. The compiler, dtc, can be downloaded, the URL is in the
  document.
 
 Ben,
 
 Does it make sense to do this as well?

You mean include lsprop ? Well, I have another version of lsprop hacked
here that can generate a source, but dtc can do it too now ... I think
we may just make dtc able to output in lsprop format too :) But I'll
talk to david (CC'd, he's the author of dtc).

Ben.





Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-02 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 14:54 -0500, Jon Loeliger wrote:
 On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
  DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
  
  Here's the fourth version of my document along with new kernel patches
  for the new improved flattened format, and the first release of the
  device-tree compiler tool. The patches will be posted as a reply to
  this email. The compiler, dtc, can be downloaded, the URL is in the
  document.
  
  ---
 
  
  dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz
 
 Ben,
 
 Here are diffs to:
 
 - Fix multi-line C-style comments.
 
 - Adjust the output of write_tree_source() such that it
   separates properties and nodes a bit better.


Excellent, thanks. Please CC david next time.

Ben.





Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-02 Thread David Gibson
On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote:
 DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
 
 Here's the fourth version of my document along with new kernel patches
 for the new improved flattened format, and the first release of the
 device-tree compiler tool. The patches will be posted as a reply to
 this email. The compiler, dtc, can be downloaded, the URL is in the
 document.

[snip]

 IV - dtc, the device tree compiler
 

 
 dtc source code can be found at
 http://ozlabs.org/~dgibson/dtc/dtc.tar.gz

I've just updated the dtc tarball with a new version.  Notable
changes:
- Corrected comment parsing
- Corrected handling of #address-cells, #size-cells properties
- Input from device tree blobs should actually work now
- Corrected autogeneration of name properties in blob/asm
  output version  0x10
- Added a TODO list

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/people/dgibson



Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-01 Thread Benjamin Herrenschmidt
DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).

Here's the fourth version of my document along with new kernel patches
for the new improved flattened format, and the first release of the
device-tree compiler tool. The patches will be posted as a reply to
this email. The compiler, dtc, can be downloaded, the URL is in the
document.

---

   Booting the Linux/ppc64 kernel without Open Firmware
   


(c) 2005 Benjamin Herrenschmidt benh at kernel.crashing.org, IBM Corp.

   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.

   May 19, 2005: Rev 0.2 - Add chapter III and bits  pieces here or
   clarifies the fact that a lot of things are
   optional, the kernel only requires a very
   small device tree, though it is encouraged
   to provide an as complete one as possible.
 
   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
 - Misc fixes
 - Define version 3 and new format version 16
   for the DT block (version 16 needs kernel
   patches, will be fwd separately).
   String block now has a size, and full path
   is replaced by unit name for more
   compactness.
   linux,phandle is made optional, only nodes
   that are referenced by other nodes need it.
   name property is now automatically
   deduced from the unit name

   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
   OF_DT_END_NODE in structure definition.
 - Change version 16 format to always align
   property data to 4 bytes. Since tokens are
   already aligned, that means no specific
   required alignement between property size
   and property data. The old style variable
   alignment would make it impossible to do
   simple insertion of properties using
   memove (thanks Milton for
   noticing). Updated kernel patch as well
 - Correct a few more alignement constraints
 - Add a chapter about the device-tree
   compiler and the textural representation of
   the tree that can be compiled by dtc.


 ToDo:

- Add some definitions of interrupt tree (simple/complex)
- Add some definitions for pci host bridges


I- Introduction
===


During the recent developpements of the Linux/ppc64 kernel, and more
specifically, the addition of new platform types outside of the old
IBM pSeries/iSeries pair, it was decided to enforce some strict rules
regarding the kernel entry and bootloader - kernel interfaces, in
order to avoid the degeneration that has become the ppc32 kernel entry
point and the way a new platform should be added to the kernel. The
legacy iSeries platform breaks those rules as it predates this scheme,
but no new board support will be accepted in the main tree that
doesn't follows them properly.

The main requirement that will be defined in more details below is
the presence of a device-tree whose format is defined after Open
Firmware specification. However, in order to make life easier
to embedded board vendors, the kernel doesn't require the device-tree
to represent every device in the system and only requires some nodes
and properties to be present. This will be described in details in
section III, but, for example, the kernel does not require you to
create a node for every PCI device in the system. It is a requirement
to have a node for PCI host bridges in order to provide interrupt
routing informations and memory/IO ranges, among others. It is also
recommended to define nodes for on chip devices and other busses that
doesn't specifically fit in an existing OF specification, like on chip
devices, this creates a great flexibility in the way the kernel can
them probe those and match drivers to device, without having to hard
code all sorts of tables. It also makes it more flexible for board
vendors to do minor hardware upgrades without impacting significantly
the kernel code or cluttering it with special cases.
 

1) Entry point
--

   There is one and one single entry point to the kernel, at the start
   of the kernel image. That entry point support two calling
   conventions:

a) Boot from Open Firmware. If your firmware is compatible
with Open Firmware (IEEE 1275) or provides an OF compatible
client interface API (support for interpret callback of
forth words isn't required), 

Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-01 Thread Benjamin Herrenschmidt
Here is the kernel patch. It applies on top of the various prom_init.c
bug fixes that I already posted today on the linuxppc-dev 
linuxppc64-dev lists (those will be in the next -mm and maybe in
2.6.12).

This patch is intended to hit upstream by 2.6.13


Index: linux-work/arch/ppc64/kernel/prom_init.c
===
--- linux-work.orig/arch/ppc64/kernel/prom_init.c   2005-06-01 
16:02:28.0 +1000
+++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-01 16:07:21.0 
+1000
@@ -1514,7 +1514,14 @@
return 0;
 }
 
-static void __init scan_dt_build_strings(phandle node, unsigned long 
*mem_start,
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
+static void __init scan_dt_build_strings(phandle node,
+unsigned long *mem_start,
 unsigned long *mem_end)
 {
unsigned long offset = reloc_offset();
@@ -1527,14 +1534,19 @@
/* get and store all property names */
prev_name = RELOC();
for (;;) {
-   
-   /* 32 is max len of name including nul. */
-   namep = make_room(mem_start, mem_end, 32, 1);
+   namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
if (call_prom(nextprop, 3, 1, node, prev_name, namep) = 0) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
}
+
+   /* skip name */
+   if (strcmp(namep, RELOC(name)) == 0) {
+   *mem_start = (unsigned long)namep;
+   prev_name = RELOC(name);
+   continue;
+   }
soff = dt_find_string(namep);
if (soff != 0) {
*mem_start = (unsigned long)namep;
@@ -1555,72 +1567,83 @@
}
 }
 
-/*
- * The Open Firmware 1275 specification states properties must be 31 bytes or
- * less, however not all firmwares obey this. Make it 64 bytes to be safe.
- */
-#define MAX_PROPERTY_NAME 64
-
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
 {
-   int l, align;
phandle child;
-   char *namep, *prev_name, *sstart, *p, *ep;
+   char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
-   char pname[MAX_PROPERTY_NAME];
-   char *path;
-
-   path = RELOC(prom_scratch);
+   static char pname[MAX_PROPERTY_NAME] __initdata;
+   int l;
 
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
-   /* get the node's full name */
+   /* get the node's full name for debugging */
+   path = RELOC(prom_scratch);
+   memset(path, 0, PROM_SCRATCH_SIZE);
+   call_prom(package-to-path, 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+   prom_debug(   %s\n, path);
+ 
+   /* get the node's full name for actual use */
namep = (char *)*mem_start;
l = call_prom(package-to-path, 3, 1, node,
  namep, *mem_end - *mem_start);
if (l = 0) {
+   int had_fixup = 0;
+ 
/* Didn't fit?  Get more room. */
if (l+1  *mem_end - *mem_start) {
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom(package-to-path, 3, 1, node, namep, l);
}
-   namep[l] = '\0';
-   /* Fixup an Apple bug where they have bogus \0 chars in the
-* middle of the path in some properties
-*/
-   for (p = namep, ep = namep + l; p  ep; p++)
-   if (*p == '\0') {
-   memmove(p, p+1, ep - p);
-   ep--; l--;
-   }
-   *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 
1, 4);
+   ep = namep + l;
+   *ep = '\0';
+   /* now try to find the unit name in that mess */
+   for (p = namep, lp = NULL; p  ep; p++) {
+   if (*p == '/')
+   lp = p + 1;
+   /* bug fix: apple's OF has a funny bug where they have
+* a '\0' in the name/path string of some nodes.
+* We fix that up here
+*/
+   if (*p == '\0') {
+   memmove(p, p+1, ep - p);
+   ep--; l--;
+   had_fixup = 1;
+   }
+   }
+   

Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-01 Thread Jon Loeliger
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
 Here's the fourth version of my document along with new kernel patches
 for the new improved flattened format, and the first release of the
 device-tree compiler tool. The patches will be posted as a reply to
 this email. The compiler, dtc, can be downloaded, the URL is in the
 document.

Ben,

Does it make sense to do this as well?

Thanks,
jdl


diff -Nur dtc.orig/lsprop.c dtc/lsprop.c
--- dtc.orig/lsprop.c   1969-12-31 18:00:00.0 -0600
+++ dtc/lsprop.c2005-06-01 11:43:01.02000 -0500
@@ -0,0 +1,221 @@
+#include stdio.h
+#include stdlib.h
+#include unistd.h
+#include sys/stat.h
+#include sys/types.h
+#include dirent.h
+
+int recurse;
+int maxbytes = 128;
+int words_per_line = 0;
+char *buf;
+
+void lsprop(FILE *f, char *name);
+void lsdir(char *name);
+
+main(int ac, char **av)
+{
+FILE *f;
+int i;
+struct stat sb;
+char *endp;
+
+while ((i = getopt(ac, av, Rm:w:)) != EOF) {
+   switch (i) {
+   case 'R':
+   recurse = 1;
+   break;
+   case 'm':
+   maxbytes = strtol(optarg, endp, 0);
+   if (endp == optarg) {
+   fprintf(stderr, %s: bad argument (%s) to -m option\n, av[0],
+   optarg);
+   exit(1);
+   }
+   maxbytes = (maxbytes + 15)  -16;
+   break;
+   case 'w':
+   words_per_line = strtol(optarg, endp, 0);
+   if (endp == optarg) {
+   fprintf(stderr, %s: bad argument (%s) to -w option\n,
+   av[0], optarg);
+   exit(1);
+   }
+   break;
+   }
+}
+
+buf = malloc(maxbytes);
+if (buf == 0) {
+   fprintf(stderr, %s: virtual memory exhausted\n, av[0]);
+   exit(1);
+}
+
+if (optind == ac)
+   lsdir(.);
+else
+   for (i = optind; i  ac; ++i) {
+   if (stat(av[i], sb)  0) {
+   perror(av[i]);
+   continue;
+   }
+   if (S_ISREG(sb.st_mode)) {
+   f = fopen(av[i], r);
+   if (f == NULL) {
+   perror(av[i]);
+   continue;
+   }
+   lsprop(f, av[i]);
+   fclose(f);
+   } else if (S_ISDIR(sb.st_mode)) {
+   lsdir(av[i]);
+   }
+   }
+exit(0);
+}
+
+void lsdir(char *name)
+{
+DIR *d;
+struct dirent *de;
+char *p, *q;
+struct stat sb;
+FILE *f;
+int np = 0;
+
+d = opendir(name);
+if (d == NULL) {
+   perror(name);
+   return;
+}
+
+p = malloc(strlen(name) + 520);
+if (p == 0) {
+   fprintf(stderr, %s: virtual memory exhausted\n, name);
+   closedir(d);
+   return;
+}
+strcpy(p, name);
+q = p + strlen(p);
+while (q  p  q[-1] == '/')
+   --q;
+if (q == p + 1  p[0] == '.')
+   q = p;
+else
+   *q++ = '/';
+
+while ((de = readdir(d)) != NULL) {
+   if (strcmp(de-d_name, .) == 0 || strcmp(de-d_name, ..) == 0)
+   continue;
+   strcpy(q, de-d_name);
+   if (stat(p, sb)  0) {
+   perror(p);
+   continue;
+   }
+   if (S_ISREG(sb.st_mode)) {
+   f = fopen(p, r);
+   if (f == NULL) {
+   perror(p);
+   } else {
+   lsprop(f, de-d_name);
+   fclose(f);
+   ++np;
+   }
+   }
+}
+rewinddir(d);
+while ((de = readdir(d)) != NULL) {
+   if (strcmp(de-d_name, .) == 0 || strcmp(de-d_name, ..) == 0)
+   continue;
+   strcpy(q, de-d_name);
+   if (lstat(p, sb)  0) {
+   perror(p);
+   continue;
+   }
+   if (S_ISDIR(sb.st_mode)) {
+   if (np)
+   printf(\n);
+   printf(%s:\n, p);
+   lsdir(p);
+   ++np;
+   }
+}
+free(p);
+closedir(d);
+}
+
+void lsprop(FILE *f, char *name)
+{
+int n, nw, npl, i, j;
+
+n = fread(buf, 1, maxbytes, f);
+if (n  0) {
+   printf(%s: read error\n, name);
+   return;
+}
+printf(%-16s, name);
+if (strlen(name)  16)
+   printf(\n\t\t);
+for (i = 0; i  n; ++i)
+   if (buf[i] = 0x7f ||
+   (buf[i]  0x20  buf[i] != '\r'  buf[i] != '\n'
+ buf[i] != '\t'  buf[i] != 0))
+   break;
+if (i == n  n != 0  (n == 1 || buf[0] != 0)  buf[n-1] == 0) {
+   printf( \);
+   for (i = 0; i  n - 1; ++i)
+   if (buf[i] == 0)
+   printf(\\n\t\t \);
+   else if (buf[i] == '\r' || buf[i] == '\n')
+   printf(\n\t\t );
+   else
+   putchar(buf[i]);
+   putchar('');
+} else if ((n  3) == 0) {
+   nw = n  2;
+   if (nw == 1) {
+   i = *(int *)buf;
+   printf( %.8x, i);
+   if (i  -0x1  !(i = 0  i = 9))
+   printf( (%d), i);
+   } else {
+   npl = words_per_line;
+   if (npl 

Booting the linux-ppc64 kernel flattened device tree v0.4

2005-06-01 Thread Jon Loeliger
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
 DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
 
 Here's the fourth version of my document along with new kernel patches
 for the new improved flattened format, and the first release of the
 device-tree compiler tool. The patches will be posted as a reply to
 this email. The compiler, dtc, can be downloaded, the URL is in the
 document.
 
 ---

 
 dtc source code can be found at http://ozlabs.org/~dgibson/dtc/dtc.tar.gz

Ben,

Here are diffs to:

- Fix multi-line C-style comments.

- Adjust the output of write_tree_source() such that it
  separates properties and nodes a bit better.

Thanks,
jdl


diff -u dtc.orig/dtc-lexer.l dtc/dtc-lexer.l
--- dtc.orig/dtc-lexer.l2005-06-01 11:44:29.02000 -0500
+++ dtc/dtc-lexer.l 2005-06-01 13:39:56.01000 -0500
@@ -34,8 +34,6 @@
 
 #include y.tab.h
 
-#undef LEXDEBUG1
-
 %}
 
 \[^]*\  {
@@ -102,7 +100,7 @@
 
 *{WS}+   /* eat whitespace */
 
-*\/\*[^*]*(\*[^/][^*])*\*\/  /* eat comments */
+*\/\*([^*]|\**[^*/])*\*+\/   /* eat C comments */
 
 *\/\/.*\n/* eat line comments */
 
diff -u dtc.orig/treesource.c dtc/treesource.c
--- dtc.orig/treesource.c   2005-06-01 11:44:29.02000 -0500
+++ dtc/treesource.c2005-06-01 13:58:33.01000 -0500
@@ -131,10 +131,16 @@
break;
}
}
-   fprintf(f, \n);
+   if (tree-children) {
+   fprintf(f, \n);
+   }
for_each_child(tree, child) {
write_tree_source(f, child, level+1);
}
write_prefix(f, level);
fprintf(f, };\n);
+
+   if (tree-next_sibling) {
+   fprintf(f, \n);
+   }
 }