added comments
gen-unicode-ctype.py: add some more comments
Don’t fill the attributes of first code point of a range twice

Alexandre Oliva> After processing a range of characters, the first
Alexandre Oliva> character of the range will have its attributes
Alexandre Oliva> filled in again, because the non-range call isn't
Alexandre Oliva> prefixed by “else”.  It's benign, but wasteful.
Don’t read the entire UnicodeData.txt file at once in fill_attributes()

Alexandre Oliva> I'm not sure it's wise for fill_attributes to load
Alexandre Oliva> the entire file into memory just to be able to index
Alexandre Oliva> the lines in an array.  It doesn't look like reading
Alexandre Oliva> the input file line by line would make the code
Alexandre Oliva> worse.

The performance doesn’t really matter here and I thought it is more
readable that way because I can easily peek at the next line when
encountering the first line of a range.  When reading the file line by
line, I have to remember the start of a range if encountered, which
doesn’t really look simpler, the code is 4 lines longer now.
I could  save  3 lines again by using

    if
    ...
    elif

instead of

    if
    ...
       continue

but somehow I don’t like that.

Alexandre Oliva> When processing ranges of characters in
Alexandre Oliva> fill_attributes, the C version uses the fields from
Alexandre Oliva> the End line, whereas the script uses those from the
Alexandre Oliva> Start line.  I guess it doesn't matter and they
Alexandre Oliva> should have the same values for most fields, but
Alexandre Oliva> perhaps it would make sense to check that they do.

Yes, it does not matter, they *must* have the same values for all
fields. But the new code checks this as well now and exits
if any field differs.
Don’t append every char that fits the class to code_point_ranges

Alexandre Oliva> It seems wasteful to append every char that fits the
Alexandre Oliva> class to code_point_ranges.  A similar effect could
Alexandre Oliva> be attained by modifying the second element of the
Alexandre Oliva> array, if it already exists, like:
Alexandre Oliva>
Alexandre Oliva>             if (code_point_ranges
Alexandre Oliva>                 and code_point_ranges[-1][-1] == code_point - 1):
Alexandre Oliva>                 if len(code_point_ranges[-1]) == 1:
Alexandre Oliva>                     code_point_ranges[-1].append(code_point)
Alexandre Oliva>                 else:
Alexandre Oliva>                     code_point_ranges[-1][-1] = code_point
Alexandre Oliva>             else:
Alexandre Oliva>                 code_point_ranges.append([code_point])

Yes. Looks uglier though and performance doesn’t really matter.
Call map_function() only once in output_charmap()

Alexandre Oliva> In output_charmap, calling map_function twice for
Alexandre Oliva> each code_point seems wasteful.  The C version does
Alexandre Oliva> that too, but just because saving the mapped char in
Alexandre Oliva> the table would make it much bigger.  Since ths
Alexandre Oliva> script doesn't build the table, it might as well save
Alexandre Oliva> the result of the first call and reuse it instead of
Alexandre Oliva> the second, like:
Alexandre Oliva>
Alexandre Oliva>         mapped = map_function(code_point)
Alexandre Oliva>         if code_point != mapped:
Alexandre Oliva> [...]
Alexandre Oliva>                          + ucs_symbol(mapped) \
Alexandre Oliva>                          + ')'

Doesn’t really make a difference in performance and appears
slightly less readable to me.