summary refs log tree commit diff stats
path: root/compiler/platform.nim
blob: ef1d00e08938c737fe46cdf95d6399de59086030 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#
#
#           The Nim Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# This module contains data about the different processors
# and operating systems.
# Note: Unfortunately if an OS or CPU is listed here this does not mean that
# Nim has been tested on this platform or that the RTL has been ported.
# Feel free to test for your excentric platform!

import
  strutils

type
  TSystemOS* = enum # Also add OS in initialization section and alias
                    # conditionals to condsyms (end of module).
    osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
    osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
    osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks
    osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch

type
  TInfoOSProp* = enum
    ospNeedsPIC,              # OS needs PIC for libraries
    ospCaseInsensitive,       # OS filesystem is case insensitive
    ospPosix,                 # OS is posix-like
    ospLacksThreadVars        # OS lacks proper __threadvar support
  TInfoOSProps* = set[TInfoOSProp]
  TInfoOS* = tuple[name: string, parDir: string, dllFrmt: string,
                   altDirSep: string, objExt: string, newLine: string,
                   pathSep: string, dirSep: string, scriptExt: string,
                   curDir: string, exeExt: string, extSep: string,
                   props: TInfoOSProps]

const
  OS*: array[succ(low(TSystemOS))..high(TSystemOS), TInfoOS] = [
     (name: "DOS",
      parDir: "..", dllFrmt: "$1.dll", altDirSep: "/", objExt: ".obj",
      newLine: "\x0D\x0A", pathSep: ";", dirSep: "\\", scriptExt: ".bat",
      curDir: ".", exeExt: ".exe", extSep: ".", props: {ospCaseInsensitive}),
     (name: "Windows", parDir: "..", dllFrmt: "$1.dll", altDirSep: "/",
      objExt: ".obj", newLine: "\x0D\x0A", pathSep: ";", dirSep: "\\",
      scriptExt: ".bat", curDir: ".", exeExt: ".exe", extSep: ".",
      props: {ospCaseInsensitive}),
     (name: "OS2", parDir: "..",
      dllFrmt: "$1.dll", altDirSep: "/",
      objExt: ".obj", newLine: "\x0D\x0A",
      pathSep: ";", dirSep: "\\",
      scriptExt: ".bat", curDir: ".",
      exeExt: ".exe", extSep: ".",
      props: {ospCaseInsensitive}),
     (name: "Linux", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "MorphOS", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "SkyOS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "Solaris", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "Irix", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "NetBSD", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "FreeBSD", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "OpenBSD", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "DragonFly", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "AIX", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "PalmOS", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".",
      props: {ospNeedsPIC}),
     (name: "QNX",
      parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", objExt: ".o",
      newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".", props: {ospNeedsPIC, ospPosix}),
     (name: "Amiga",
      parDir: "..", dllFrmt: "$1.library", altDirSep: "/", objExt: ".o",
      newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".", props: {ospNeedsPIC}),
     (name: "Atari",
      parDir: "..", dllFrmt: "$1.dll", altDirSep: "/", objExt: ".o",
      newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: "", curDir: ".",
      exeExt: ".tpp", extSep: ".", props: {ospNeedsPIC}),
     (name: "Netware",
      parDir: "..", dllFrmt: "$1.nlm", altDirSep: "/", objExt: "",
      newLine: "\x0D\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh",
      curDir: ".", exeExt: ".nlm", extSep: ".", props: {ospCaseInsensitive}),
     (name: "MacOS", parDir: "::", dllFrmt: "$1Lib", altDirSep: ":",
      objExt: ".o", newLine: "\x0D", pathSep: ",", dirSep: ":", scriptExt: "",
      curDir: ":", exeExt: "", extSep: ".", props: {ospCaseInsensitive}),
     (name: "MacOSX", parDir: "..", dllFrmt: "lib$1.dylib", altDirSep: ":",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
     (name: "Haiku", parDir: "..", dllFrmt: "lib$1.so", altDirSep: ":",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
     (name: "Android", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     (name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
      scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
      props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
     (name: "Genode", pardir: "..", dllFrmt: "$1.lib.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: "", curDir: "/", exeExt: "", extSep: ".",
      props: {ospNeedsPIC, ospLacksThreadVars}),

     (name: "JS", parDir: "..",
      dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A",
      pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".",
      exeExt: "", extSep: ".", props: {}),
     (name: "NimVM", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", props: {}),
     (name: "Standalone", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
      props: {}),
     (name: "NintendoSwitch", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
      objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
      scriptExt: ".sh", curDir: ".", exeExt: ".elf", extSep: ".",
      props: {ospNeedsPIC, ospPosix}),
     ]

type
  TSystemCPU* = enum # Also add CPU for in initialization section and
                     # alias conditionals to condsyms (end of module).
    cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
    cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel,
    cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430, cpuSparc64,
    cpuMips64, cpuMips64el, cpuRiscV64

type
  TEndian* = enum
    littleEndian, bigEndian
  TInfoCPU* = tuple[name: string, intSize: int, endian: TEndian,
                    floatSize, bit: int]

const
  EndianToStr*: array[TEndian, string] = ["littleEndian", "bigEndian"]
  CPU*: array[succ(low(TSystemCPU))..high(TSystemCPU), TInfoCPU] = [
    (name: "i386", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
    (name: "m68k", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
    (name: "alpha", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
    (name: "powerpc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
    (name: "powerpc64", intSize: 64, endian: bigEndian, floatSize: 64,bit: 64),
    (name: "powerpc64el", intSize: 64, endian: littleEndian, floatSize: 64,bit: 64),
    (name: "sparc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
    (name: "vm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
    (name: "ia64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
    (name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
    (name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
    (name: "mipsel", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
    (name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
    (name: "arm64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
    (name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
    (name: "nimvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
    (name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
    (name: "msp430", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
    (name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
    (name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
    (name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
    (name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)]

type
  Target* = object
    targetCPU*, hostCPU*: TSystemCPU
    targetOS*, hostOS*: TSystemOS
    intSize*: int
    floatSize*: int
    ptrSize*: int
    tnl*: string                # target newline

proc setTarget*(t: var Target; o: TSystemOS, c: TSystemCPU) =
  assert(c != cpuNone)
  assert(o != osNone)
  #echo "new Target: OS: ", o, " CPU: ", c
  t.targetCPU = c
  t.targetOS = o
  t.intSize = CPU[c].intSize div 8
  t.floatSize = CPU[c].floatSize div 8
  t.ptrSize = CPU[c].bit div 8
  t.tnl = OS[o].newLine

proc nameToOS*(name: string): TSystemOS =
  for i in countup(succ(osNone), high(TSystemOS)):
    if cmpIgnoreStyle(name, OS[i].name) == 0:
      return i
  result = osNone

proc nameToCPU*(name: string): TSystemCPU =
  for i in countup(succ(cpuNone), high(TSystemCPU)):
    if cmpIgnoreStyle(name, CPU[i].name) == 0:
      return i
  result = cpuNone

proc setTargetFromSystem*(t: var Target) =
  t.hostOS = nameToOS(system.hostOS)
  t.hostCPU = nameToCPU(system.hostCPU)
  t.setTarget(t.hostOS, t.hostCPU)
an class="p">("not accessible", self.wid) self.color_reset() return if self.target.empty(): self.color(tuple(base_color + ['empty'])) self.addnstr("empty", self.wid) self.color_reset() return self._set_scroll_begin() copied = [f.path for f in self.fm.copy_buffer] selected_i = self.target.pointer for line in range(self.hei): i = line + self.scroll_begin if line > self.hei: break try: drawn = self.target.files[i] except IndexError: break tagged = self.fm.tags and drawn.realpath in self.fm.tags if tagged: tagged_marker = self.fm.tags.marker(drawn.realpath) else: tagged_marker = " " # Extract linemode-related information from the drawn object metadata = None current_linemode = drawn.linemode_dict[drawn._linemode] if current_linemode.uses_metadata: metadata = self.fm.metadata.get_metadata(drawn.path) if not all(getattr(metadata, tag) for tag in current_linemode.required_metadata): current_linemode = drawn.linemode_dict[linemode.DEFAULT_LINEMODE] metakey = hash(repr(sorted(metadata.items()))) if metadata else 0 key = (self.wid, selected_i == i, drawn.marked, self.main_column, drawn.path in copied, tagged_marker, drawn.infostring, drawn.vcsfilestatus, drawn.vcsremotestatus, self.fm.do_cut, current_linemode.name, metakey) if key in drawn.display_data: self.execute_curses_batch(line, drawn.display_data[key]) self.color_reset() continue text = current_linemode.filetitle(drawn, metadata) if drawn.marked and (self.main_column or \ self.settings.display_tags_in_all_columns): text = " " + text # Computing predisplay data. predisplay contains a list of lists # [string, colorlst] where string is a piece of string to display, # and colorlst a list of contexts that we later pass to the # colorscheme, to compute the curses attribute. predisplay_left = [] predisplay_right = [] space = self.wid # selection mark tagmark = self._draw_tagged_display(tagged, tagged_marker) tagmarklen = self._total_len(tagmark) if space - tagmarklen > 2: predisplay_left += tagmark space -= tagmarklen # vcs data vcsstring = self._draw_vcsstring_display(drawn) vcsstringlen = self._total_len(vcsstring) if space - vcsstringlen > 2: predisplay_right += vcsstring space -= vcsstringlen # info string infostring = [] infostringlen = 0 try: infostringdata = current_linemode.infostring(drawn, metadata) if infostringdata: infostring.append([" " + infostringdata + " ", ["infostring"]]) except NotImplementedError: infostring = self._draw_infostring_display(drawn, space) if infostring: infostringlen = self._total_len(infostring) if space - infostringlen > 2: predisplay_right = infostring + predisplay_right space -= infostringlen textstring = self._draw_text_display(text, space) textstringlen = self._total_len(textstring) predisplay_left += textstring space -= textstringlen if space > 0: predisplay_left.append([' ' * space, []]) elif space < 0: raise Exception("Error: there is not enough space to write " "the text. I have computed spaces wrong.") # Computing display data. Now we compute the display_data list # ready to display in curses. It is a list of lists [string, attr] this_color = base_color + list(drawn.mimetype_tuple) + \ self._draw_directory_color(i, drawn, copied) display_data = [] drawn.display_data[key] = display_data predisplay = predisplay_left + predisplay_right for txt, color in predisplay: attr = self.settings.colorscheme.get_attr(*(this_color + color)) display_data.append([txt, attr]) self.execute_curses_batch(line, display_data) self.color_reset() def _total_len(self, predisplay): return sum([len(WideString(s)) for s, L in predisplay]) def _draw_text_display(self, text, space): wtext = WideString(text) wext = WideString(splitext(text)[1]) wellip = WideString(self.ellipsis[self.settings.unicode_ellipsis]) if len(wtext) > space: wtext = wtext[:max(1, space - len(wext) - len(wellip))] + wellip + wext # Truncate again if still too long. if len(wtext) > space: wtext = wtext[:max(0, space - len(wellip))] + wellip return [[str(wtext), []]] def _draw_tagged_display(self, tagged, tagged_marker): tagged_display = [] if (self.main_column or self.settings.display_tags_in_all_columns) \ and self.wid > 2: if tagged: tagged_display.append([tagged_marker, ['tag_marker']]) else: tagged_display.append([" ", ['tag_marker']]) return tagged_display def _draw_infostring_display(self, drawn, space): infostring_display = [] if self.display_infostring and drawn.infostring \ and self.settings.display_size_in_main_column: infostring = str(drawn.infostring) + " " if len(infostring) <= space: infostring_display.append([infostring, ['infostring']]) return infostring_display def _draw_vcsstring_display(self, drawn): vcsstring_display = [] if self.settings.vcs_aware and (drawn.vcsfilestatus or \ drawn.vcsremotestatus): if drawn.vcsfilestatus: vcsstr, vcscol = self.vcsfilestatus_symb[drawn.vcsfilestatus] else: vcsstr = " " vcscol = [] vcsstring_display.append([vcsstr, ['vcsfile'] + vcscol]) if drawn.vcsremotestatus: vcsstr, vcscol = self.vcsremotestatus_symb[ drawn.vcsremotestatus] else: vcsstr = " " vcscol = [] vcsstring_display.append([vcsstr, ['vcsremote'] + vcscol]) elif self.target.has_vcschild: vcsstring_display.append([" ", []]) return vcsstring_display def _draw_directory_color(self, i, drawn, copied): this_color = [] if i == self.target.pointer: this_color.append('selected') if drawn.marked: this_color.append('marked') if self.fm.tags and drawn.realpath in self.fm.tags: this_color.append('tagged') if drawn.is_directory: this_color.append('directory') else: this_color.append('file') if drawn.stat: mode = drawn.stat.st_mode if mode & stat.S_IXUSR: this_color.append('executable') if stat.S_ISFIFO(mode): this_color.append('fifo') if stat.S_ISSOCK(mode): this_color.append('socket') if drawn.is_device: this_color.append('device') if drawn.path in copied: this_color.append('cut' if self.fm.do_cut else 'copied') if drawn.is_link: this_color.append('link') this_color.append(drawn.exists and 'good' or 'bad') return this_color def _get_scroll_begin(self): """Determines scroll_begin (the position of the first displayed file)""" offset = self.settings.scroll_offset dirsize = len(self.target) winsize = self.hei halfwinsize = winsize // 2 index = self.target.pointer or 0 original = self.target.scroll_begin projected = index - original upper_limit = winsize - 1 - offset lower_limit = offset if original < 0: return 0 if dirsize < winsize: return 0 if halfwinsize < offset: return min( dirsize - winsize, max( 0, index - halfwinsize )) if original > dirsize - winsize: self.target.scroll_begin = dirsize - winsize return self._get_scroll_begin() if projected < upper_limit and projected > lower_limit: return original if projected > upper_limit: return min( dirsize - winsize, original + (projected - upper_limit)) if projected < upper_limit: return max( 0, original - (lower_limit - projected)) return original def _set_scroll_begin(self): """Updates the scroll_begin value""" self.scroll_begin = self._get_scroll_begin() self.target.scroll_begin = self.scroll_begin def scroll(self, n): """scroll down by n lines""" self.need_redraw = True self.target.move(down=n) self.target.scroll_begin += 3 * n def __str__(self): return self.__class__.__name__ + ' at level ' + str(self.level)