1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# file generate_symbols_images.py
5# This file is part of LyX, the document processor.
6# Licence details can be found in the file COPYING.
7
8# Full author contact details are available in file CREDITS
9
10from __future__ import print_function
11import sys,string,re,os,os.path
12import io
13
14def get_code(code, font):
15    # computer modern fonts use a strange encoding
16    cmfonts = ["cmex", "cmr", "cmm", "cmsy"]
17    if font not in cmfonts:
18        return code
19    if code < 10:
20        return code+161
21    if code < 11:
22        return code+162
23    elif code <= 32:
24        return code+163
25    else:
26        return code
27
28font_names = {}
29symbols = {}
30xsymbols = {}
31
32ignore_list = ["not", "braceld", "bracerd", "bracelu", "braceru",
33               "lmoustache", "rmoustache", "lgroup", "rgroup", "bracevert"]
34
35def process(file):
36    fh = io.open(file, 'r', encoding='ascii')
37    lines = fh.readlines()
38    fh.close()
39    package, ext = os.path.splitext(os.path.basename(file))
40    if ext != ".sty":
41        package = ''
42    mdsymbolcode = 0
43
44    n = len(lines)
45    for i in range(n):
46        line = lines[i]
47        mo =  re.match(r'\s*%.*', line)
48        if mo != None:
49            continue
50        next_line = ""
51        if i+1 < n:
52            next_line = lines[i+1]
53
54        # some entries are spread over two lines so we join the next line
55        # to the current one, (if current line contains a comment, we remove it)
56        line = line.split('%')[0]+next_line
57
58        mo =  re.match(r'.*\\DeclareSymbolFont\s*\{(.*?)\}\s*\{(.*?)\}\s*\{(.*?)\}.*', line)
59        if mo != None:
60            font_names[mo.group(1)] = mo.group(3)
61
62        mo =  re.match(r'^\s*\\mdsy\@DeclareSymbolFont\s*\{(.*?)\}\s*\{(.*?)\}\s*\{(.*?)\}.*', line)
63        if mo != None:
64            font_names[mo.group(1)] = mo.group(3)
65
66        # \mdsy@setslot resets the counter for \mdsy@DeclareSymbol
67        mo =  re.match(r'^\s*\\mdsy\@setslot\s*\{(.*?)\}.*', line)
68        if mo != None:
69            mdsymbolcode = int(mo.group(1))
70
71        # \mdsy@nextslot increments the counter for \mdsy@DeclareSymbol
72        mo =  re.match(r'^\s*\\mdsy\@nextslot.*', line)
73        if mo != None:
74            mdsymbolcode = mdsymbolcode + 1
75
76        mo =  re.match(r'.*\\(\\mdsy\@)?DeclareMath(Symbol|Delimiter)\s*\{?\\(\w*?)\}?\s*\{?\\(.*?)\}?\s*\{(.*?)\}\s*\{([\'"]?)(.*?)\}.*', line)
77        code = -1
78        try:
79            if mo != None:
80                symbol = mo.group(3)
81                type = mo.group(4)
82                font = mo.group(5)
83                if mo.group(6) == '':
84                    code = int(mo.group(7))
85                elif mo.group(6) == '"':
86                    code = int(mo.group(7), 16)
87                else:
88                    code = int(mo.group(7), 8)
89            else:
90                mo = re.match(r'.*\\edef\\(\w*?)\{.*?\{\\hexnumber@\\sym(.*?)\}(.*?)\}', line)
91                if mo != None:
92                    symbol = mo.group(1)
93                    type = "mathord"
94                    font = mo.group(2)
95                    code = int(mo.group(3), 16)
96        except ValueError:
97                code = -1
98
99        if mo == None:
100            mo =  re.match(r'^\s*\\mdsy\@DeclareSymbol\s*\{(.*?)\}\s*\{(.*?)\}\s*\{\\(.*?)\}.*', line)
101            if mo != None:
102                symbol = mo.group(1)
103                type = mo.group(3)
104                font = mo.group(2)
105                code = mdsymbolcode
106                mdsymbolcode = mdsymbolcode + 1
107
108        if mo == None:
109            mo =  re.match(r'^\s*\\mdsy\@DeclareAlias\s*\{(.*?)\}\s*\{(.*?)\}\s*\{\\(.*?)\}.*', line)
110            if mo != None:
111                symbol = mo.group(1)
112                type = mo.group(3)
113                font = mo.group(2)
114                code = mdsymbolcode - 1
115
116        if mo != None and symbol not in ignore_list:
117            mo2 = re.match(r'\s*\\def\\(.*?)\{', next_line)
118            if mo2 != None and symbol == mo2.group(1)+"op":
119                sys.stderr.write("%s -> %s\n" % (symbol, mo2.group(1)))
120                symbol = mo2.group(1)
121
122            if font in font_names:
123                font = font_names[font]
124
125            code = get_code(code, font)
126            if code < 0:
127                continue
128
129            xcode = 0
130            if symbol in xsymbols:
131                xcode = xsymbols[symbol]
132                del xsymbols[symbol]
133
134            if symbol in symbols:
135                sys.stderr.write(symbol+ " exists\n")
136                if code != symbols[symbol]:
137                    sys.stderr.write("code is not equal!!!\n")
138            else:
139                symbols[symbol] = code
140                if package == '':
141                    print("%-18s %-4s %3d %3d %-6s" % (symbol,font,code,xcode,type))
142                else:
143                    print("%-18s %-4s %3d %3d %-9s x  %s" % (symbol,font,code,xcode,type,package))
144
145
146path = os.path.split(sys.argv[0])[0]
147fh = io.open(os.path.join(path, "x-font"), 'r', encoding='ascii')
148lines = fh.readlines()
149fh.close()
150for line in lines:
151    x = line.split()
152    symbol = x[0]
153    code = int(x[1], 16)
154    xsymbols[symbol] = code
155
156for file in sys.argv[1:]:
157    print("# Generated from " + os.path.basename(file) + "\n")
158    process(file)
159    print()
160
161exceptions = [
162    ("neq", "x", 0, 185, "mathrel"),
163    ("textdegree", "x", 0, 176, "mathord"),
164    ("cong", "x", 0, 64, "mathrel"),
165    ("surd", "x", 0, 214, "mathord")
166]
167
168if "leq" in xsymbols:
169    sys.exit(0)
170
171for x in exceptions:
172    print("%-18s %-4s %3d %3d %-6s" % x)
173    if x[0] in xsymbols:
174        del xsymbols[x[0]]
175
176print ("""
177lyxbar             cmsy 161   0 mathord
178lyxeq              cmr   61   0 mathord
179lyxdabar           msa   57   0 mathord
180lyxright           msa   75   0 mathord
181lyxleft            msa   76   0 mathord
182""")
183
184for symbol in xsymbols.keys():
185    sys.stderr.write(symbol+"\n")
186