home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2803 < prev    next >
Internet Message Format  |  1991-02-19  |  62KB

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: Python 0.9.1 part 11/21
  4. Message-ID: <2973@charon.cwi.nl>
  5. Date: 19 Feb 91 17:42:05 GMT
  6.  
  7. : This is a shell archive.
  8. : Extract with 'sh this_file'.
  9. :
  10. : Extract part 01 first since it makes all directories
  11. echo 'Start of pack.out, part 11 out of 21:'
  12. if test -s 'lib/Buttons.py'
  13. then echo '*** I will not over-write existing file lib/Buttons.py'
  14. else
  15. echo 'x - lib/Buttons.py'
  16. sed 's/^X//' > 'lib/Buttons.py' << 'EOF'
  17. X# Module 'Buttons'
  18. X
  19. X
  20. X# Import module 'rect' renamed as '_rect' to avoid exporting it on
  21. X# 'from Buttons import *'
  22. X#
  23. Ximport rect
  24. X_rect = rect
  25. Xdel rect
  26. X
  27. X
  28. X# Field indices in mouse event detail
  29. X#
  30. X_HV = 0
  31. X_CLICKS = 1
  32. X_BUTTON = 2
  33. X_MASK = 3
  34. X
  35. X
  36. X# LabelAppearance provides defaults for all appearance methods.
  37. X# selected state not visible
  38. X# disabled --> crossed out
  39. X# hilited  --> inverted
  40. X#
  41. Xclass LabelAppearance():
  42. X    #
  43. X    # Initialization
  44. X    #
  45. X    def init_appearance(self):
  46. X        self.bounds = _rect.empty
  47. X        self.enabled = 1
  48. X        self.hilited = 0
  49. X        self.selected = 0
  50. X        self.text = ''
  51. X    #
  52. X    # Size enquiry
  53. X    #
  54. X    def minsize(self, m):
  55. X        try:
  56. X            self.text = self.text
  57. X        except NameError:
  58. X            self.text = ''
  59. X        return m.textwidth(self.text) + 6, m.lineheight() + 6
  60. X    #
  61. X    def getbounds(self):
  62. X        return self.bounds
  63. X    #
  64. X    # Changing the parameters
  65. X    #
  66. X    def settext(self, text):
  67. X        self.text = text
  68. X        if self.bounds <> _rect.empty:
  69. X            self.recalctextpos()
  70. X            self.redraw()
  71. X    #
  72. X    def setbounds(self, bounds):
  73. X        if self.bounds <> _rect.empty:
  74. X            self.parent.change(self.bounds)
  75. X        self.bounds = bounds
  76. X        if self.bounds <> _rect.empty:
  77. X            self.recalc()
  78. X            self.parent.change(bounds)
  79. X    #
  80. X    # Changing the state bits
  81. X    #
  82. X    def enable(self, flag):
  83. X        if flag <> self.enabled:
  84. X            self.enabled = flag
  85. X            if self.bounds <> _rect.empty:
  86. X                self.flipenable(self.parent.begindrawing())
  87. X    #
  88. X    def hilite(self, flag):
  89. X        if flag <> self.hilited:
  90. X            self.hilited = flag
  91. X            if self.bounds <> _rect.empty:
  92. X                self.fliphilite(self.parent.begindrawing())
  93. X    #
  94. X    def select(self, flag):
  95. X        if flag <> self.selected:
  96. X            self.selected = flag
  97. X            if self.bounds <> _rect.empty:
  98. X                self.redraw()
  99. X    #
  100. X    # Recalculate the box bounds and text position.
  101. X    # This can be overridden by buttons that draw different boxes
  102. X    # or want their text in a different position.
  103. X    #
  104. X    def recalc(self):
  105. X        if self.bounds <> _rect.empty:
  106. X            self.recalcbounds()
  107. X            self.recalctextpos()
  108. X    #
  109. X    def recalcbounds(self):
  110. X        self.hilitebounds = _rect.inset(self.bounds, (3, 3))
  111. X        self.crossbounds = self.bounds
  112. X    #
  113. X    def recalctextpos(self):
  114. X        (left, top), (right, bottom) = self.bounds
  115. X        m = self.parent.beginmeasuring()
  116. X        h = (left + right - m.textwidth(self.text)) / 2
  117. X        v = (top + bottom - m.lineheight()) / 2
  118. X        self.textpos = h, v
  119. X    #
  120. X    # Generic drawing interface.
  121. X    # Do not override redraw() or draw() methods; override drawit() c.s.
  122. X    #
  123. X    def redraw(self):
  124. X        if self.bounds <> _rect.empty:
  125. X            self.draw(self.parent.begindrawing(), self.bounds)
  126. X    #
  127. X    def draw(self, (d, area)):
  128. X        area = _rect.intersect(area, self.bounds)
  129. X        if area = _rect.empty:
  130. X            return
  131. X        d.cliprect(area)
  132. X        d.erase(self.bounds)
  133. X        self.drawit(d)
  134. X        d.noclip()
  135. X    #
  136. X    # The drawit() method is fairly generic but may be overridden.
  137. X    #
  138. X    def drawit(self, d):
  139. X        self.drawpict(d)
  140. X        if self.text:
  141. X            d.text(self.textpos, self.text)
  142. X        if not self.enabled:
  143. X            self.flipenable(d)
  144. X        if self.hilited:
  145. X            self.fliphilite(d)
  146. X    #
  147. X    # Default drawing detail functions.
  148. X    # Overriding these is normally sufficient to get different
  149. X    # appearances.
  150. X    #
  151. X    def drawpict(self, d):
  152. X        pass
  153. X    #
  154. X    def flipenable(self, d):
  155. X        _xorcross(d, self.crossbounds)
  156. X    #
  157. X    def fliphilite(self, d):
  158. X        d.invert(self.hilitebounds)
  159. X
  160. X
  161. X# ButtonAppearance displays a centered string in a box.
  162. X# selected --> bold border
  163. X# disabled --> crossed out
  164. X# hilited  --> inverted
  165. X#
  166. Xclass ButtonAppearance() = LabelAppearance():
  167. X    #
  168. X    def drawpict(self, d):
  169. X        d.box(_rect.inset(self.bounds, (1, 1)))
  170. X        if self.selected:
  171. X            # Make a thicker box
  172. X            d.box(self.bounds)
  173. X            d.box(_rect.inset(self.bounds, (2, 2)))
  174. X            d.box(_rect.inset(self.bounds, (3, 3)))
  175. X    #
  176. X
  177. X
  178. X# CheckAppearance displays a small square box and a left-justified string.
  179. X# selected --> a cross appears in the box
  180. X# disabled --> whole button crossed out
  181. X# hilited  --> box is inverted
  182. X#
  183. Xclass CheckAppearance() = LabelAppearance():
  184. X    #
  185. X    def minsize(self, m):
  186. X        width, height = m.textwidth(self.text) + 6, m.lineheight() + 6
  187. X        return width + height + m.textwidth(' '), height
  188. X    #
  189. X    def drawpict(self, d):
  190. X        d.box(self.boxbounds)
  191. X        if self.selected: _xorcross(d, self.boxbounds)
  192. X    #
  193. X    def recalcbounds(self):
  194. X        LabelAppearance.recalcbounds(self)
  195. X        (left, top), (right, bottom) = self.bounds
  196. X        self.size = bottom - top - 4
  197. X        self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
  198. X        self.hilitebounds = self.boxbounds
  199. X    #
  200. X    def recalctextpos(self):
  201. X        m = self.parent.beginmeasuring()
  202. X        (left, top), (right, bottom) = self.boxbounds
  203. X        h = right + m.textwidth(' ')
  204. X        v = top + (self.size - m.lineheight()) / 2
  205. X        self.textpos = h, v
  206. X    #
  207. X
  208. X
  209. X# RadioAppearance displays a round indicator and a left-justified string.
  210. X# selected --> a dot appears in the indicator
  211. X# disabled --> whole button crossed out
  212. X# hilited  --> indicator is inverted
  213. X#
  214. Xclass RadioAppearance() = CheckAppearance():
  215. X    #
  216. X    def drawpict(self, d):
  217. X        (left, top), (right, bottom) = self.boxbounds
  218. X        radius = self.size / 2
  219. X        h, v = left + radius, top + radius
  220. X        d.circle((h, v), radius)
  221. X        if self.selected:
  222. X            some = radius/3
  223. X            d.paint((h-some, v-some), (h+some, v+some))
  224. X    #
  225. X
  226. X
  227. X# NoReactivity ignores mouse events.
  228. X#
  229. Xclass NoReactivity():
  230. X    def init_reactivity(self): pass
  231. X
  232. X
  233. X# BaseReactivity defines hooks and asks for mouse events,
  234. X# but provides only dummy mouse event handlers.
  235. X# The trigger methods call the corresponding hooks set by the user.
  236. X# Hooks (and triggers) mean the following:
  237. X# down_hook    called on some mouse-down events
  238. X# move_hook    called on some mouse-move events
  239. X# up_hook    called on mouse-up events
  240. X# on_hook    called for buttons with on/off state, when it goes on
  241. X# hook        called when a button 'fires' or a radiobutton goes on
  242. X# There are usually extra conditions, e.g., hooks are only called
  243. X# when the button is enabled, or active, or selected (on).
  244. X#
  245. Xclass BaseReactivity():
  246. X    #
  247. X    def init_reactivity(self):
  248. X        self.down_hook = self.move_hook = self.up_hook = \
  249. X            self.on_hook = self.off_hook = \
  250. X            self.hook = self.active = 0
  251. X        self.parent.need_mouse(self)
  252. X    #
  253. X    def mousetest(self, hv):
  254. X        return _rect.pointinrect(hv, self.bounds)
  255. X    #
  256. X    def mouse_down(self, detail):
  257. X        pass
  258. X    #
  259. X    def mouse_move(self, detail):
  260. X        pass
  261. X    #
  262. X    def mouse_up(self, detail):
  263. X        pass
  264. X    #
  265. X    def down_trigger(self):
  266. X        if self.down_hook: self.down_hook(self)
  267. X    #
  268. X    def move_trigger(self):
  269. X        if self.move_hook: self.move_hook(self)
  270. X    #
  271. X    def up_trigger(self):
  272. X        if self.up_hook: self.up_hook(self)
  273. X    #
  274. X    def on_trigger(self):
  275. X        if self.on_hook: self.on_hook(self)
  276. X    #
  277. X    def off_trigger(self):
  278. X        if self.off_hook: self.off_hook(self)
  279. X    #
  280. X    def trigger(self):
  281. X        if self.hook: self.hook(self)
  282. X
  283. X
  284. X# ToggleReactivity acts like a simple pushbutton.
  285. X# It toggles its hilite state on mouse down events.
  286. X#
  287. Xclass ToggleReactivity() = BaseReactivity():
  288. X    #
  289. X    def mouse_down(self, detail):
  290. X        if self.enabled and self.mousetest(detail[_HV]):
  291. X            self.active = 1
  292. X            self.hilite(not self.hilited)
  293. X            self.down_trigger()
  294. X    #
  295. X    def mouse_move(self, detail):
  296. X        if self.active:
  297. X            self.move_trigger()
  298. X    #
  299. X    def mouse_up(self, detail):
  300. X        if self.active:
  301. X            self.up_trigger()
  302. X            self.active = 0
  303. X    #
  304. X    def down_trigger(self):
  305. X        if self.hilited:
  306. X            self.on_trigger()
  307. X        else:
  308. X            self.off_trigger()
  309. X        self.trigger()
  310. X    #
  311. X
  312. X
  313. X# TriggerReactivity acts like a fancy pushbutton.
  314. X# It hilites itself while the mouse is down within its bounds.
  315. X#
  316. Xclass TriggerReactivity() = BaseReactivity():
  317. X    #
  318. X    def mouse_down(self, detail):
  319. X        if self.enabled and self.mousetest(detail[_HV]):
  320. X            self.active = 1
  321. X            self.hilite(1)
  322. X            self.down_trigger()
  323. X    #
  324. X    def mouse_move(self, detail):
  325. X        if self.active:
  326. X            self.hilite(self.mousetest(detail[_HV]))
  327. X            if self.hilited:
  328. X                self.move_trigger()
  329. X    #
  330. X    def mouse_up(self, detail):
  331. X        if self.active:
  332. X            self.hilite(self.mousetest(detail[_HV]))
  333. X            if self.hilited:
  334. X                self.up_trigger()
  335. X                self.trigger()
  336. X            self.active = 0
  337. X            self.hilite(0)
  338. X    #
  339. X
  340. X
  341. X# CheckReactivity handles mouse events like TriggerReactivity,
  342. X# It overrides the up_trigger method to flip its selected state.
  343. X#
  344. Xclass CheckReactivity() = TriggerReactivity():
  345. X    #
  346. X    def up_trigger(self):
  347. X        self.select(not self.selected)
  348. X        if self.selected:
  349. X            self.on_trigger()
  350. X        else:
  351. X            self.off_trigger()
  352. X        self.trigger()
  353. X
  354. X
  355. X# RadioReactivity turns itself on and the other buttons in its group
  356. X# off when its up_trigger method is called.
  357. X#
  358. Xclass RadioReactivity() = TriggerReactivity():
  359. X    #
  360. X    def init_reactivity(self):
  361. X        TriggerReactivity.init_reactivity(self)
  362. X        self.group = []
  363. X    #
  364. X    def up_trigger(self):
  365. X        for b in self.group:
  366. X            if b <> self:
  367. X                if b.selected:
  368. X                    b.select(0)
  369. X                    b.off_trigger()
  370. X        self.select(1)
  371. X        self.on_trigger()
  372. X        self.trigger()
  373. X
  374. X
  375. X# Auxiliary class for 'define' method.
  376. X# Call the initializers in the right order.
  377. X#
  378. Xclass Define():
  379. X    #
  380. X    def define(self, parent):
  381. X        self.parent = parent
  382. X        parent.addchild(self)
  383. X        self.init_appearance()
  384. X        self.init_reactivity()
  385. X        return self
  386. X    #
  387. X    def destroy(self):
  388. X        self.parent = 0
  389. X    #
  390. X    def definetext(self, (parent, text)):
  391. X        self = self.define(parent)
  392. X        self.settext(text)
  393. X        return self
  394. X
  395. X
  396. X# Subroutine to cross out a rectangle.
  397. X#
  398. Xdef _xorcross(d, bounds):
  399. X    ((left, top), (right, bottom)) = bounds
  400. X    # This is s bit funny to make it look better
  401. X    left = left + 2
  402. X    right = right - 2
  403. X    top = top + 2
  404. X    bottom = bottom - 3
  405. X    d.xorline(((left, top), (right, bottom)))
  406. X    d.xorline((left, bottom), (right, top))
  407. X
  408. X
  409. X# Ready-made button classes.
  410. X#
  411. Xclass Label() = NoReactivity(), LabelAppearance(), Define(): pass
  412. Xclass PushButton() = TriggerReactivity(), ButtonAppearance(), Define(): pass
  413. Xclass CheckButton() = CheckReactivity(), CheckAppearance(), Define(): pass
  414. Xclass RadioButton() = RadioReactivity(), RadioAppearance(), Define(): pass
  415. Xclass ToggleButton() = ToggleReactivity(), ButtonAppearance(), Define(): pass
  416. EOF
  417. fi
  418. if test -s 'lib/TclUtil.py'
  419. then echo '*** I will not over-write existing file lib/TclUtil.py'
  420. else
  421. echo 'x - lib/TclUtil.py'
  422. sed 's/^X//' > 'lib/TclUtil.py' << 'EOF'
  423. X# Utilities used by 'Tcl' emulator.
  424. X
  425. X
  426. X# Many functions in this file parse specific constructs from strings.
  427. X# In order to limit the number of slice operations (the strings can
  428. X# be very large), they always receive indices into the string that
  429. X# indicate the slice of the string that should be considered.
  430. X# The return value is in general another index, pointing to the first
  431. X# character in the string beyond the recognized construct.
  432. X# Errors are reported as exceptions (TclSyntaxError, TclMatchingError).
  433. X# A few functions have multiple return values.
  434. X
  435. X
  436. X# For efficiency, the Tcl "tokenizing" routines used pre-compiled
  437. X# regular expressions.  This is less readable but should be much faster
  438. X# than scanning the string a character at a time.
  439. X#
  440. X# The global variables
  441. X# containing the compiled regexp's are named _foo_prog where foo is
  442. X# an indication of the function that uses them.
  443. X#
  444. X# The patterns always
  445. X# have the form <something>* so they always match at the start of the
  446. X# search buffer---maybe with the empty string.  This makes it possible
  447. X# to use the expression "_foo_prog.exec(str, i)[0][1]" to find the first
  448. X# character beyond the matched string.  Note that this may be beyond the
  449. X# end variable -- where this matters, "min(i, end)" is used.
  450. X
  451. X# Constructs that cannot
  452. X# be recognized by a finite automaton (like matching braces) are scanned
  453. X# by a hybrid technique where the regular expression excludes the
  454. X# braces.
  455. X#
  456. X# Many regular expressions contain an expression that matches
  457. X# a Tcl backslash sequence as a subpart:
  458. X#    \\\\C?M?(.|\n)
  459. X#
  460. X# This is a bit hard to
  461. X# read because the backslash contained in it must be doubled twice:
  462. X# once to get past Python's backslash mechanism, once to get past that
  463. X# of regular expressions.  It uses (.|\n) to match absolutely
  464. X# *every character*, becase the MULTILINE regular expression package does
  465. X# not accept '\n' as a match for '.'.
  466. X#
  467. X# There is also a simplification in the pattern for backslashes:
  468. X# *any* single character following a backslash is escaped,
  469. X# so hex and octal
  470. X# excapes are not scanned fully.  The forms \Cx, \Mx and \CMx are
  471. X# scanned correctly, as these may hide a special character.
  472. X# (This does not invalidate the recognition of strings, although the
  473. X# match is effectuated in a different way than by the Backslash function.)
  474. X
  475. Ximport regexp
  476. X
  477. X
  478. X# Exceptions raised for various error conditions.
  479. X
  480. XTclAssertError = 'Tcl assert error'
  481. XTclSyntaxError = 'Tcl syntax error'
  482. XTclRuntimeError = 'Tcl runtime error'
  483. XTclMatchingError = 'Tcl matching error'
  484. X
  485. X
  486. X# Find a variable name.
  487. X# A variable name is either a (possiblly empty) sequence of letters,
  488. X# digits and underscores, or anything enclosed in matching braces.
  489. X# Return the index past the end of the name.
  490. X
  491. X_varname_prog = regexp.compile('[a-zA-Z0-9_]*')
  492. X
  493. Xdef FindVarName(str, i, end):
  494. X    if i < end and str[i] = '{': return BalanceBraces(str, i, end)
  495. X    i = _varname_prog.exec(str, i)[0][1]
  496. X    return min(i, end)
  497. X
  498. X
  499. X# Split a list into its elements.
  500. X# Return a list of elements (strings).
  501. X
  502. Xdef SplitList(str):
  503. X    i, end = 0, len(str)
  504. X    list = []
  505. X    while 1:
  506. X        i = SkipSpaces(str, i, end)
  507. X        if i >= end: break
  508. X        j = i
  509. X        i = FindNextElement(str, i, end)
  510. X        if str[j] = '{' and str[i-1] = '}':
  511. X            element = str[j+1:i-1]
  512. X        else:
  513. X            element = Collapse(str[j:i])
  514. X        list.append(element)
  515. X    return list
  516. X
  517. X
  518. X# Find the next element from a list.
  519. X
  520. X_element_prog = regexp.compile('([^ \t\n\\]+|\\\\C?M?(.|\n))*')
  521. X
  522. Xdef FindNextElement(str, i, end):
  523. X    if i < end and str[i] = '{':
  524. X        i = BalanceBraces(str, i, end)
  525. X        if i < end and str[i] not in ' \t\n':
  526. X            raise TclSyntaxError, 'Garbage after } in list'
  527. X        return i
  528. X    i = _element_prog.exec(str, i)[0][1]
  529. X    return min(i, end)
  530. X
  531. X
  532. X# Copy a string, expanding all backslash sequences.
  533. X
  534. X_collapse_prog = regexp.compile('(\n|[^\\]+)*')
  535. X
  536. Xdef Collapse(str):
  537. X    if '\\' not in str: return str
  538. X    i, end = 0, len(str)
  539. X    result = ''
  540. X    while i < end:
  541. X        j = _collapse_prog.exec(str, i)[0][1]
  542. X        j = min(j, end)
  543. X        result = result + str[i:j]
  544. X        if j >= end: break
  545. X        c = str[j]
  546. X        if c <> '\\': raise TclAssertError, 'collapse error'
  547. X        x, i = Backslash(str, j, end)
  548. X        result = result + x
  549. X    return result
  550. X
  551. X
  552. X# Find the next full command.
  553. X# Return a list of begin, end indices of words in the string,
  554. X# and an index pointing just after the terminating newline or
  555. X# semicolon.
  556. X# Initial spaces are skipped.
  557. X# If the command begins with '#', it is considered empty and
  558. X# characters until '\n' are skipped.
  559. X
  560. X_eol_prog = regexp.compile('[^\n]*')
  561. X
  562. Xdef FindNextCommand(str, i, end, bracketed):
  563. X    i = SkipSpaces(str, i, end)
  564. X    if i >= end: return [], end
  565. X    if str[i] = '#':
  566. X        i = _eol_prog.exec(str, i)
  567. X        i = min(i, end)
  568. X        if i < end and str[i] = '\n': i = i+1
  569. X        return [], i
  570. X    if bracketed: terminators = [';']
  571. X    else: terminators = [';', '\n']
  572. X    list = []
  573. X    while i < end:
  574. X        j = FindNextWord(str, i, end)
  575. X        word = str[i:j]
  576. X        if word in terminators:
  577. X            i = j
  578. X            break
  579. X        if word <> '\n': list.append(i, j)
  580. X        i = SkipSpaces(str, j, end)
  581. X    return list, i
  582. X
  583. X
  584. X# Find the next word of a command.
  585. X# Semicolon and newline terminate words but also count as a word
  586. X# themselves.
  587. X# The start index must point to the start of the word.
  588. X
  589. X_word_prog = regexp.compile('([^ \t\n;[\\]+|\\\\C?M?(.|\n))*')
  590. X
  591. Xdef FindNextWord(str, i, end):
  592. X    if i >= end: return end
  593. X    if str[i] in '{"':
  594. X        if str[i] = '{': i = BalanceBraces(str, i, end)
  595. X        else: i = BalanceQuotes(str, i, end)
  596. X        if i >= end or str[i] in ' \t\n;': return min(i, end)
  597. X        raise TclSyntaxError, 'Garbage after } or "'
  598. X    begin = i
  599. X    while i < end:
  600. X        i = _word_prog.exec(str, i)[0][1]
  601. X        if i >= end:
  602. X            i = end
  603. X            break
  604. X        c = str[i]
  605. X        if c in ' \t': break
  606. X        if c in ';\n':
  607. X            if i = begin: i = i+1
  608. X            break
  609. X        if c = '[': i = BalanceBrackets(str, i, end)
  610. X        else: raise TclAssertError, 'word error'
  611. X    return i
  612. X
  613. X
  614. X# Parse balanced brackets from str[i:end].
  615. X# str[i] must be '['.
  616. X# Returns end such that str[i:end] ends with ']'
  617. X# and contains balanced braces and brackets.
  618. X
  619. X_brackets_prog = regexp.compile('([^][{\\]+|\n|\\\\C?M?(.|\n))*')
  620. X
  621. Xdef BalanceBrackets(str, i, end):
  622. X    if i >= end or str[i] <> '[':
  623. X        raise TclAssertError, 'BalanceBrackets'
  624. X    nesting = 0
  625. X    while i < end:
  626. X        i = _brackets_prog.exec(str, i)[0][1]
  627. X        if i >= end: break
  628. X        c = str[i]
  629. X        if c = '{': i = BalanceBraces(str, i, end)
  630. X        else:
  631. X            i = i+1
  632. X            if c = '[': nesting = nesting + 1
  633. X            elif c = ']':
  634. X                nesting = nesting - 1
  635. X                if nesting = 0: return i
  636. X            else: raise TclAssertError, 'brackets error'
  637. X    raise TclMatchingError, 'Unmatched bracket ([)'
  638. X
  639. X
  640. X# Parse balanced braces from str[i:end].
  641. X# str[i] must be '{'.
  642. X# Returns end such that str[i:end] ends with '}'
  643. X# and contains balanced braces.
  644. X
  645. X_braces_prog = regexp.compile('([^{}\\]+|\n|\\\\C?M?(.|\n))*')
  646. X
  647. Xdef BalanceBraces(str, i, end):
  648. X    if i >= end or str[i] <> '{':
  649. X        raise TclAssertError, 'BalanceBraces'
  650. X    nesting = 0
  651. X    while i < end:
  652. X        i = _braces_prog.exec(str, i)[0][1]
  653. X        if i >= end: break
  654. X        c = str[i]
  655. X        i = i+1
  656. X        if c = '{': nesting = nesting + 1
  657. X        elif c = '}':
  658. X            nesting = nesting - 1
  659. X            if nesting = 0: return i
  660. X        else: raise TclAssertError, 'braces error'
  661. X    raise TclMatchingError, 'Unmatched brace ({)'
  662. X
  663. X
  664. X# Parse double quotes from str[i:end].
  665. X# str[i] must be '"'.
  666. X# Returns end such that str[i:end] ends with an unescaped '"'.
  667. X
  668. X_quotes_prog = regexp.compile('([^"\\]+|\n|\\\\C?M?(.|\n))*')
  669. X
  670. Xdef BalanceQuotes(str, i, end):
  671. X    if i >= end or str[i] <> '"':
  672. X        raise TclAssertError, 'BalanceQuotes'
  673. X    i = _quotes_prog.exec(str, i+1)[0][1]
  674. X    if i < end and str[i] = '"': return i+1
  675. X    raise TclMatchingError, 'Unmatched quote (")'
  676. X
  677. X
  678. X# Static data used by Backslash()
  679. X
  680. X_bstab = {}
  681. X_bstab['n'] = '\n'
  682. X_bstab['r'] = '\r'
  683. X_bstab['t'] = '\t'
  684. X_bstab['b'] = '\b'
  685. X_bstab['e'] = '\033'
  686. X_bstab['\n'] = ''
  687. Xfor c in ' {}[]$";\\': _bstab[c] = c
  688. Xdel c
  689. X
  690. X# Backslash interpretation.
  691. X# First character must be a backslash.
  692. X# Return a pair (<replacement string>, <end of sequence>).
  693. X# Unrecognized or incomplete backslash sequences are not errors;
  694. X# this takes only the backslash itself off the string.
  695. X
  696. Xdef Backslash(str, i, end):
  697. X    if i >= end or str[i] <> '\\':
  698. X        raise TclAssertError, 'Backslash'
  699. X    i = i+1
  700. X    if i = end: return '\\', i
  701. X    c = str[i]
  702. X    i = i+1
  703. X    if _bstab.has_key(c): return _bstab[c], i
  704. X    if c = 'C':
  705. X        if i = end: return '\\', i-1
  706. X        c = str[i]
  707. X        i = i+1
  708. X        if c = 'M':
  709. X            if i = end: return '\\', i-2
  710. X            c = str[i]
  711. X            i = i+1
  712. X            x = ord(c) % 040 + 0200
  713. X        else:
  714. X            x = ord(c) % 040
  715. X        return chr(x), i
  716. X    elif c = 'M':
  717. X        if i = end: return '\\', i-1
  718. X        c = str[i]
  719. X        i = i+1
  720. X        x = ord(c)
  721. X        if x < 0200: x = x + 0200
  722. X        return chr(x), i
  723. X    elif c and c in '0123456789':
  724. X        x = ord(c) - ord('0')
  725. X        end = min(end, i+2)
  726. X        while i < end:
  727. X            c = str[i]
  728. X            if c not in '0123456789': break
  729. X            i = i+1
  730. X            x = x*8 + ord(c) - ord('0')
  731. X        return ord(x), i
  732. X    else:
  733. X        # Not something that we recognize
  734. X        return '\\', i-1
  735. X
  736. X
  737. X# Skip over spaces and tabs (but not newlines).
  738. X
  739. X_spaces_prog = regexp.compile('[ \t]*')
  740. X
  741. Xdef SkipSpaces(str, i, end):
  742. X    i = _spaces_prog.exec(str, i)[0][1]
  743. X    return min(i, end)
  744. X
  745. X
  746. X# Concatenate the elements of a list with intervening spaces.
  747. X
  748. Xdef Concat(argv):
  749. X    result = ''
  750. X    sep = ''
  751. X    for arg in argv:
  752. X        result = result + (sep + arg)
  753. X        sep = ' '
  754. X    return result
  755. X
  756. X
  757. X# Concatenate list elements, adding braces etc. to make them parseable
  758. X# again with SplitList.
  759. X
  760. Xdef BuildList(argv):
  761. X    result = ''
  762. X    sep = ''
  763. X    for arg in argv:
  764. X        arg = AddBraces(arg)
  765. X        result = result + (sep + arg)
  766. X        sep = ' '
  767. X    return result
  768. X
  769. X
  770. X# Add braces around a string if necessary to make it parseable by SplitList.
  771. X
  772. Xdef AddBraces(str):
  773. X    # Special case for empty string
  774. X    if str = '': return '{}'
  775. X    # See if it contains balanced braces
  776. X    res = '{' + str + '}'
  777. X    if TryNextElement(res):
  778. X        # See if it would survive unquoted
  779. X        # XXX should escape [] and $ as well???
  780. X        if TryNextElement(str) and Collapse(str) = str: return str
  781. X        # No -- return with added braces
  782. X        return res
  783. X    # Unbalanced braces.  Add backslashes before suspect characters
  784. X    res = ''
  785. X    for c in str:
  786. X        if c in '$\\[]{} ;': c = '\\' + c
  787. X        elif c = '\n': c = '\\n'
  788. X        elif c = '\t': c = '\\t'
  789. X        res = res + c
  790. X    return res
  791. X
  792. X
  793. Xdef TryNextElement(str):
  794. X    end = len(str)
  795. X    try:
  796. X        i = FindNextElement(str, 0, end)
  797. X        return i = end
  798. X    except (TclSyntaxError, TclMatchingError):
  799. X        return 0
  800. EOF
  801. fi
  802. if test -s 'lib/testall.py'
  803. then echo '*** I will not over-write existing file lib/testall.py'
  804. else
  805. echo 'x - lib/testall.py'
  806. sed 's/^X//' > 'lib/testall.py' << 'EOF'
  807. X# Module 'testall'
  808. X#
  809. X# Python test set, should exercise:
  810. X#    - all lexical and grammatical constructs
  811. X#    - all opcodes from "opcode.h"
  812. X#    - all operations on all object types
  813. X#    - all builtin functions
  814. X# Ideally also:
  815. X#    - all possible exception situations (Thank God we've got 'try')
  816. X#    - all boundary cases
  817. X
  818. X
  819. XTestFailed = 'testall -- test failed'        # Exception
  820. X
  821. X
  822. X#########################################################
  823. X# Part 1.  Test all lexical and grammatical constructs.
  824. X# This just tests whether the parser accepts them all.
  825. X#########################################################
  826. X
  827. Xprint '1. Parser'
  828. X
  829. Xprint '1.1 Tokens'
  830. X
  831. Xprint '1.1.1 Backslashes'
  832. X
  833. X# Backslash means line continuation:
  834. Xx = 1 \
  835. X+ 1
  836. Xif x <> 2: raise TestFailed, 'backslash for line continuation'
  837. X
  838. X# Backslash does not means continuation in comments :\
  839. Xx = 0
  840. Xif x <> 0: raise TestFailed, 'backslash ending comment'
  841. X
  842. Xprint '1.1.2 Number formats'
  843. X
  844. Xif 0xff <> 255: raise TestFailed, 'hex number'
  845. Xif 0377 <> 255: raise TestFailed, 'octal number'
  846. Xx = 3.14
  847. Xx = 0.314
  848. Xx = 3e14
  849. Xx = 3E14
  850. Xx = 3e-14
  851. X
  852. Xprint '1.2 Grammar'
  853. X
  854. Xprint 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE
  855. X# XXX can't test in a script -- this rule is only used when interactive
  856. X
  857. Xprint 'file_input' # (NEWLINE | stmt)* ENDMARKER
  858. X# Being tested as this very moment this very module
  859. X
  860. Xprint 'expr_input' # testlist NEWLINE
  861. X# XXX Hard to test -- used only in calls to input()
  862. X
  863. Xprint 'eval_input' # testlist ENDMARKER
  864. Xx = eval('1, 0 or 1')
  865. X
  866. Xprint 'funcdef' # 'def' NAME parameters ':' suite
  867. X### parameters: '(' [fplist] ')'
  868. X### fplist: fpdef (',' fpdef)*
  869. X### fpdef: NAME | '(' fplist ')'
  870. Xdef f1(): pass
  871. Xdef f2(one_argument): pass
  872. Xdef f3(two, arguments): pass
  873. Xdef f4(two, (compound, (arguments))): pass
  874. X
  875. X### stmt: simple_stmt | compound_stmt
  876. X### simple_stmt: expr_stmt | print_stmt  | pass_stmt | del_stmt | flow_stmt | import_stmt
  877. X# Tested below
  878. X
  879. Xprint 'expr_stmt' # (exprlist '=')* exprlist NEWLINE
  880. X1
  881. X1, 2, 3
  882. Xx = 1
  883. Xx = 1, 2, 3
  884. Xx = y = z = 1, 2, 3
  885. Xx, y, z = 1, 2, 3
  886. Xabc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
  887. X# NB these variables are deleted below
  888. X
  889. Xprint 'print_stmt' # 'print' (test ',')* [test] NEWLINE
  890. Xprint 1, 2, 3
  891. Xprint 1, 2, 3,
  892. Xprint
  893. Xprint 0 or 1, 0 or 1,
  894. Xprint 0 or 1
  895. X
  896. Xprint 'del_stmt' # 'del' exprlist NEWLINE
  897. Xdel abc
  898. Xdel x, y, (z, xyz)
  899. X
  900. Xprint 'pass_stmt' # 'pass' NEWLINE
  901. Xpass
  902. X
  903. Xprint 'flow_stmt' # break_stmt | return_stmt | raise_stmt
  904. X# Tested below
  905. X
  906. Xprint 'break_stmt' # 'break' NEWLINE
  907. Xwhile 1: break
  908. X
  909. Xprint 'return_stmt' # 'return' [testlist] NEWLINE
  910. Xdef g1(): return
  911. Xdef g2(): return 1
  912. Xg1()
  913. Xx = g2()
  914. X
  915. Xprint 'raise_stmt' # 'raise' expr [',' expr] NEWLINE
  916. Xtry: raise RuntimeError, 'just testing'
  917. Xexcept RuntimeError: pass
  918. Xtry: raise KeyboardInterrupt
  919. Xexcept KeyboardInterrupt: pass
  920. X
  921. Xprint 'import_stmt' # 'import' NAME (',' NAME)* NEWLINE | 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE
  922. X[1]
  923. Ximport sys
  924. X[2]
  925. Ximport time, math
  926. X[3]
  927. Xfrom time import sleep
  928. X[4]
  929. Xfrom math import *
  930. X[5]
  931. Xfrom sys import modules, ps1, ps2
  932. X[6]
  933. X
  934. X### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
  935. X# Tested below
  936. X
  937. Xprint 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
  938. Xif 1: pass
  939. Xif 1: pass
  940. Xelse: pass
  941. Xif 0: pass
  942. Xelif 0: pass
  943. Xif 0: pass
  944. Xelif 0: pass
  945. Xelif 0: pass
  946. Xelif 0: pass
  947. Xelse: pass
  948. X
  949. Xprint 'while_stmt' # 'while' test ':' suite ['else' ':' suite]
  950. Xwhile 0: pass
  951. Xwhile 0: pass
  952. Xelse: pass
  953. X
  954. Xprint 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
  955. X[1]
  956. Xfor i in 1, 2, 3: pass
  957. X[2]
  958. Xfor i, j, k in (): pass
  959. Xelse: pass
  960. X[3]
  961. X
  962. Xprint 'try_stmt' # 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite]
  963. X### except_clause: 'except' [expr [',' expr]]
  964. Xtry: pass
  965. Xtry: 1/0
  966. Xexcept RuntimeError: pass
  967. Xtry: 1/0
  968. Xexcept EOFError: pass
  969. Xexcept TypeError, msg: pass
  970. Xexcept RuntimeError, msg: pass
  971. Xexcept: pass
  972. Xtry: pass
  973. Xfinally: pass
  974. Xtry: 1/0
  975. Xexcept: pass
  976. Xfinally: pass
  977. X
  978. Xprint 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
  979. Xif 1: pass
  980. Xif 1:
  981. X    pass
  982. Xif 1:
  983. X    #
  984. X    #
  985. X    #
  986. X    pass
  987. X    pass
  988. X    #
  989. X    pass
  990. X    #
  991. X
  992. Xprint 'test' # and_test ('or' and_test)*
  993. X### and_test: not_test ('and' not_test)*
  994. X### not_test: 'not' not_test | comparison
  995. X### comparison: expr (comp_op expr)*
  996. X### comp_op: '<'|'>'|'='|'>' '='|'<' '='|'<' '>'|'in'|'not' 'in'|'is'|'is' 'not'
  997. Xif 1: pass
  998. Xif 1 = 1: pass
  999. Xif 1 < 1 > 1 = 1 >= 1 <= 1 <> 1 in 1 not in 1 is 1 is not 1: pass
  1000. Xif not 1 = 1 = 1: pass
  1001. Xif not 1 = 1 and 1 and 1: pass
  1002. Xif 1 and 1 or 1 and 1 and 1 or not 1 = 1 = 1 and 1: pass
  1003. X
  1004. Xprint 'expr' # term (('+'|'-') term)*
  1005. Xx = 1
  1006. Xx = 1 + 1
  1007. Xx = 1 - 1 - 1
  1008. Xx = 1 - 1 + 1 - 1 + 1
  1009. X
  1010. Xprint 'term' # factor (('*'|'/'|'%') factor)*
  1011. Xx = 1 * 1
  1012. Xx = 1 / 1
  1013. Xx = 1 % 1
  1014. Xx = 1 / 1 * 1 % 1
  1015. X
  1016. Xprint 'factor' # ('+'|'-') factor | atom trailer*
  1017. X### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
  1018. X### subscript: expr | [expr] ':' [expr]
  1019. Xx = +1
  1020. Xx = -1
  1021. Xx = 1
  1022. Xc = sys.ps1[0]
  1023. Xx = time.time()
  1024. Xx = sys.modules['time'].time()
  1025. Xa = '01234'
  1026. Xc = a[0]
  1027. Xc = a[0:5]
  1028. Xc = a[:5]
  1029. Xc = a[0:]
  1030. Xc = a[:]
  1031. Xc = a[-5:]
  1032. Xc = a[:-1]
  1033. Xc = a[-4:-3]
  1034. X
  1035. Xprint 'atom' # '(' [testlist] ')' | '[' [testlist] ']' | '{' '}' | '`' testlist '`' | NAME | NUMBER | STRING
  1036. Xx = (1)
  1037. Xx = (1 or 2 or 3)
  1038. Xx = (1 or 2 or 3, 2, 3)
  1039. Xx = []
  1040. Xx = [1]
  1041. Xx = [1 or 2 or 3]
  1042. Xx = [1 or 2 or 3, 2, 3]
  1043. Xx = []
  1044. Xx = {}
  1045. Xx = `x`
  1046. Xx = x
  1047. Xx = 'x'
  1048. Xx = 123
  1049. X
  1050. X### exprlist: expr (',' expr)* [',']
  1051. X### testlist: test (',' test)* [',']
  1052. X# These have been exercised enough above
  1053. X
  1054. Xprint 'classdef' # 'class' NAME parameters ['=' baselist] ':' suite
  1055. X### baselist: atom arguments (',' atom arguments)*
  1056. X### arguments: '(' [testlist] ')'
  1057. Xclass B(): pass
  1058. Xclass C1() = B(): pass
  1059. Xclass C2() = B(): pass
  1060. Xclass D() = C1(), C2(), B(): pass
  1061. Xclass C():
  1062. X    def meth1(self): pass
  1063. X    def meth2(self, arg): pass
  1064. X    def meth3(self, (a1, a2)): pass
  1065. X
  1066. X
  1067. X#########################################################
  1068. X# Part 2.  Test all opcodes from "opcode.h"
  1069. X#########################################################
  1070. X
  1071. Xprint '2. Opcodes'
  1072. Xprint 'XXX Not yet fully implemented'
  1073. X
  1074. Xprint '2.1 try inside for loop'
  1075. Xn = 0
  1076. Xfor i in range(10):
  1077. X    n = n+i
  1078. X    try: 1/0
  1079. X    except NameError: pass
  1080. X    except RuntimeError: pass
  1081. X    except TypeError: pass
  1082. X    finally: pass
  1083. X    try: pass
  1084. X    except: pass
  1085. X    try: pass
  1086. X    finally: pass
  1087. X    n = n+i
  1088. Xif n <> 90:
  1089. X    raise TestFailed, 'try inside for'
  1090. X
  1091. X
  1092. X#########################################################
  1093. X# Part 3.  Test all operations on all object types
  1094. X#########################################################
  1095. X
  1096. Xprint '3. Object types'
  1097. Xprint 'XXX Not yet implemented'
  1098. X
  1099. X
  1100. X#########################################################
  1101. X# Part 4.  Test all built-in functions
  1102. X#########################################################
  1103. X
  1104. Xprint '4. Built-in functions'
  1105. X
  1106. Xprint 'abs'
  1107. Xif abs(0) <> 0: raise TestFailed, 'abs(0)'
  1108. Xif abs(1234) <> 1234: raise TestFailed, 'abs(1234)'
  1109. Xif abs(-1234) <> 1234: raise TestFailed, 'abs(-1234)'
  1110. Xif abs(0.0) <> 0.0: raise TestFailed, 'abs(0.0)'
  1111. Xif abs(3.14) <> 3.14: raise TestFailed, 'abs(3.14)'
  1112. Xif abs(-3.14) <> 3.14: raise TestFailed, 'abs(-3.14)'
  1113. X
  1114. Xprint 'dir'
  1115. Xif 'x' not in dir(): raise TestFailed, 'dir()'
  1116. Xif 'modules' not in dir(sys): raise TestFailed, 'dir(sys)'
  1117. X
  1118. Xprint 'divmod'
  1119. Xif divmod(12, 7) <> (1, 5): raise TestFailed, 'divmod(12, 7)'
  1120. Xif divmod(-12, 7) <> (-2, 2): raise TestFailed, 'divmod(-12, 7)'
  1121. Xif divmod(12, -7) <> (-2, -2): raise TestFailed, 'divmod(12, -7)'
  1122. Xif divmod(-12, -7) <> (1, -5): raise TestFailed, 'divmod(-12, -7)'
  1123. X
  1124. Xprint 'eval'
  1125. Xif eval('1+1') <> 2: raise TestFailed, 'eval(\'1+1\')'
  1126. X
  1127. Xprint 'exec'
  1128. Xexec('z=1+1\n')
  1129. Xif z <> 2: raise TestFailed, 'exec(\'z=1+1\'\\n)'
  1130. X
  1131. Xprint 'float'
  1132. Xif float(3.14) <> 3.14: raise TestFailed, 'float(3.14)'
  1133. Xif float(314) <> 314.0: raise TestFailed, 'float(314)'
  1134. X
  1135. Xprint 'input'
  1136. X# Can't test in a script
  1137. X
  1138. Xprint 'int'
  1139. Xif int(100) <> 100: raise TestFailed, 'int(100)'
  1140. Xif int(3.14) <> 3: raise TestFailed, 'int(3.14)'
  1141. X
  1142. Xprint 'len'
  1143. Xif len('123') <> 3: raise TestFailed, 'len(\'123\')'
  1144. Xif len(()) <> 0: raise TestFailed, 'len(())'
  1145. Xif len((1, 2, 3, 4)) <> 4: raise TestFailed, 'len((1, 2, 3, 4))'
  1146. Xif len([1, 2, 3, 4]) <> 4: raise TestFailed, 'len([1, 2, 3, 4])'
  1147. Xif len({}) <> 0: raise TestFailed, 'len({})'
  1148. X
  1149. Xprint 'min'
  1150. Xif min('123123') <> '1': raise TestFailed, 'min(\'123123\')'
  1151. Xif min(1, 2, 3) <> 1: raise TestFailed, 'min(1, 2, 3)'
  1152. Xif min((1, 2, 3, 1, 2, 3)) <> 1: raise TestFailed, 'min((1, 2, 3, 1, 2, 3))'
  1153. Xif min([1, 2, 3, 1, 2, 3]) <> 1: raise TestFailed, 'min([1, 2, 3, 1, 2, 3])'
  1154. X
  1155. Xprint 'max'
  1156. Xif max('123123') <> '3': raise TestFailed, 'max(\'123123\')'
  1157. Xif max(1, 2, 3) <> 3: raise TestFailed, 'max(1, 2, 3)'
  1158. Xif max((1, 2, 3, 1, 2, 3)) <> 3: raise TestFailed, 'max((1, 2, 3, 1, 2, 3))'
  1159. Xif max([1, 2, 3, 1, 2, 3]) <> 3: raise TestFailed, 'max([1, 2, 3, 1, 2, 3])'
  1160. X
  1161. Xprint 'open'
  1162. Xprint 'NB! This test creates a file named "@test" in the current directory.'
  1163. Xfp = open('@test', 'w')
  1164. Xfp.write('The quick brown fox jumps over the lazy dog')
  1165. Xfp.write('.\n')
  1166. Xfp.write('Dear John\n')
  1167. Xfp.write('XXX'*100)
  1168. Xfp.write('YYY'*100)
  1169. Xfp.close()
  1170. Xdel fp
  1171. Xfp = open('@test', 'r')
  1172. Xif fp.readline() <> 'The quick brown fox jumps over the lazy dog.\n':
  1173. X    raise TestFailed, 'readline()'
  1174. Xif fp.readline(4) <> 'Dear': raise TestFailed, 'readline(4) # short'
  1175. Xif fp.readline(100) <> ' John\n': raise TestFailed, 'readline(100)'
  1176. Xif fp.read(300) <> 'XXX'*100: raise TestFailed, 'read(300)'
  1177. Xif fp.read(1000) <> 'YYY'*100: raise TestFailed, 'read(1000) # truncate'
  1178. Xfp.close()
  1179. Xdel fp
  1180. X
  1181. Xprint 'range'
  1182. Xif range(3) <> [0, 1, 2]: raise TestFailed, 'range(3)'
  1183. Xif range(1, 5) <> [1, 2, 3, 4]: raise TestFailed, 'range(1, 5)'
  1184. Xif range(0) <> []: raise TestFailed, 'range(0)'
  1185. Xif range(-3) <> []: raise TestFailed, 'range(-3)'
  1186. Xif range(1, 10, 3) <> [1, 4, 7]: raise TestFailed, 'range(1, 10, 3)'
  1187. Xif range(5, -5, -3) <> [5, 2, -1, -4]: raise TestFailed, 'range(5, -5, -3)'
  1188. X
  1189. Xprint 'raw_input'
  1190. Xsavestdin = sys.stdin
  1191. Xtry:
  1192. X    sys.stdin = open('@test', 'r')
  1193. X    if raw_input() <> 'The quick brown fox jumps over the lazy dog.':
  1194. X        raise TestFailed, 'raw_input()'
  1195. X    if raw_input('testing\n') <> 'Dear John':
  1196. X        raise TestFailed, 'raw_input(\'testing\\n\')'
  1197. Xfinally:
  1198. X    sys.stdin = savestdin
  1199. X
  1200. Xprint 'reload'
  1201. Ximport string
  1202. Xreload(string)
  1203. X
  1204. Xprint 'type'
  1205. Xif type('') <> type('123') or type('') = type(()):
  1206. X    raise TestFailed, 'type()'
  1207. X
  1208. X
  1209. Xprint 'Passed all tests.'
  1210. X
  1211. Xtry:
  1212. X    import mac
  1213. X    unlink = mac.unlink
  1214. Xexcept NameError:
  1215. X    try:
  1216. X        import posix
  1217. X        unlink = posix.unlink
  1218. X    except NameError:
  1219. X        pass
  1220. X
  1221. Xunlink('@test')
  1222. Xprint 'Unlinked @test'
  1223. EOF
  1224. fi
  1225. if test -s 'src/listobject.c'
  1226. then echo '*** I will not over-write existing file src/listobject.c'
  1227. else
  1228. echo 'x - src/listobject.c'
  1229. sed 's/^X//' > 'src/listobject.c' << 'EOF'
  1230. X/***********************************************************
  1231. XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  1232. XNetherlands.
  1233. X
  1234. X                        All Rights Reserved
  1235. X
  1236. XPermission to use, copy, modify, and distribute this software and its 
  1237. Xdocumentation for any purpose and without fee is hereby granted, 
  1238. Xprovided that the above copyright notice appear in all copies and that
  1239. Xboth that copyright notice and this permission notice appear in 
  1240. Xsupporting documentation, and that the names of Stichting Mathematisch
  1241. XCentrum or CWI not be used in advertising or publicity pertaining to
  1242. Xdistribution of the software without specific, written prior permission.
  1243. X
  1244. XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1245. XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1246. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  1247. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1248. XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  1249. XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  1250. XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1251. X
  1252. X******************************************************************/
  1253. X
  1254. X/* List object implementation */
  1255. X
  1256. X#include "allobjects.h"
  1257. X
  1258. Xobject *
  1259. Xnewlistobject(size)
  1260. X    int size;
  1261. X{
  1262. X    int i;
  1263. X    listobject *op;
  1264. X    if (size < 0) {
  1265. X        err_badcall();
  1266. X        return NULL;
  1267. X    }
  1268. X    op = (listobject *) malloc(sizeof(listobject));
  1269. X    if (op == NULL) {
  1270. X        return err_nomem();
  1271. X    }
  1272. X    if (size <= 0) {
  1273. X        op->ob_item = NULL;
  1274. X    }
  1275. X    else {
  1276. X        op->ob_item = (object **) malloc(size * sizeof(object *));
  1277. X        if (op->ob_item == NULL) {
  1278. X            free((ANY *)op);
  1279. X            return err_nomem();
  1280. X        }
  1281. X    }
  1282. X    NEWREF(op);
  1283. X    op->ob_type = &Listtype;
  1284. X    op->ob_size = size;
  1285. X    for (i = 0; i < size; i++)
  1286. X        op->ob_item[i] = NULL;
  1287. X    return (object *) op;
  1288. X}
  1289. X
  1290. Xint
  1291. Xgetlistsize(op)
  1292. X    object *op;
  1293. X{
  1294. X    if (!is_listobject(op)) {
  1295. X        err_badcall();
  1296. X        return -1;
  1297. X    }
  1298. X    else
  1299. X        return ((listobject *)op) -> ob_size;
  1300. X}
  1301. X
  1302. Xobject *
  1303. Xgetlistitem(op, i)
  1304. X    object *op;
  1305. X    int i;
  1306. X{
  1307. X    if (!is_listobject(op)) {
  1308. X        err_badcall();
  1309. X        return NULL;
  1310. X    }
  1311. X    if (i < 0 || i >= ((listobject *)op) -> ob_size) {
  1312. X        err_setstr(IndexError, "list index out of range");
  1313. X        return NULL;
  1314. X    }
  1315. X    return ((listobject *)op) -> ob_item[i];
  1316. X}
  1317. X
  1318. Xint
  1319. Xsetlistitem(op, i, newitem)
  1320. X    register object *op;
  1321. X    register int i;
  1322. X    register object *newitem;
  1323. X{
  1324. X    register object *olditem;
  1325. X    if (!is_listobject(op)) {
  1326. X        if (newitem != NULL)
  1327. X            DECREF(newitem);
  1328. X        err_badcall();
  1329. X        return -1;
  1330. X    }
  1331. X    if (i < 0 || i >= ((listobject *)op) -> ob_size) {
  1332. X        if (newitem != NULL)
  1333. X            DECREF(newitem);
  1334. X        err_setstr(IndexError, "list assignment index out of range");
  1335. X        return -1;
  1336. X    }
  1337. X    olditem = ((listobject *)op) -> ob_item[i];
  1338. X    ((listobject *)op) -> ob_item[i] = newitem;
  1339. X    if (olditem != NULL)
  1340. X        DECREF(olditem);
  1341. X    return 0;
  1342. X}
  1343. X
  1344. Xstatic int
  1345. Xins1(self, where, v)
  1346. X    listobject *self;
  1347. X    int where;
  1348. X    object *v;
  1349. X{
  1350. X    int i;
  1351. X    object **items;
  1352. X    if (v == NULL) {
  1353. X        err_badcall();
  1354. X        return -1;
  1355. X    }
  1356. X    items = self->ob_item;
  1357. X    RESIZE(items, object *, self->ob_size+1);
  1358. X    if (items == NULL) {
  1359. X        err_nomem();
  1360. X        return -1;
  1361. X    }
  1362. X    if (where < 0)
  1363. X        where = 0;
  1364. X    if (where > self->ob_size)
  1365. X        where = self->ob_size;
  1366. X    for (i = self->ob_size; --i >= where; )
  1367. X        items[i+1] = items[i];
  1368. X    INCREF(v);
  1369. X    items[where] = v;
  1370. X    self->ob_item = items;
  1371. X    self->ob_size++;
  1372. X    return 0;
  1373. X}
  1374. X
  1375. Xint
  1376. Xinslistitem(op, where, newitem)
  1377. X    object *op;
  1378. X    int where;
  1379. X    object *newitem;
  1380. X{
  1381. X    if (!is_listobject(op)) {
  1382. X        err_badcall();
  1383. X        return -1;
  1384. X    }
  1385. X    return ins1((listobject *)op, where, newitem);
  1386. X}
  1387. X
  1388. Xint
  1389. Xaddlistitem(op, newitem)
  1390. X    object *op;
  1391. X    object *newitem;
  1392. X{
  1393. X    if (!is_listobject(op)) {
  1394. X        err_badcall();
  1395. X        return -1;
  1396. X    }
  1397. X    return ins1((listobject *)op,
  1398. X        (int) ((listobject *)op)->ob_size, newitem);
  1399. X}
  1400. X
  1401. X/* Methods */
  1402. X
  1403. Xstatic void
  1404. Xlist_dealloc(op)
  1405. X    listobject *op;
  1406. X{
  1407. X    int i;
  1408. X    for (i = 0; i < op->ob_size; i++) {
  1409. X        if (op->ob_item[i] != NULL)
  1410. X            DECREF(op->ob_item[i]);
  1411. X    }
  1412. X    if (op->ob_item != NULL)
  1413. X        free((ANY *)op->ob_item);
  1414. X    free((ANY *)op);
  1415. X}
  1416. X
  1417. Xstatic void
  1418. Xlist_print(op, fp, flags)
  1419. X    listobject *op;
  1420. X    FILE *fp;
  1421. X    int flags;
  1422. X{
  1423. X    int i;
  1424. X    fprintf(fp, "[");
  1425. X    for (i = 0; i < op->ob_size && !StopPrint; i++) {
  1426. X        if (i > 0) {
  1427. X            fprintf(fp, ", ");
  1428. X        }
  1429. X        printobject(op->ob_item[i], fp, flags);
  1430. X    }
  1431. X    fprintf(fp, "]");
  1432. X}
  1433. X
  1434. Xobject *
  1435. Xlist_repr(v)
  1436. X    listobject *v;
  1437. X{
  1438. X    object *s, *t, *comma;
  1439. X    int i;
  1440. X    s = newstringobject("[");
  1441. X    comma = newstringobject(", ");
  1442. X    for (i = 0; i < v->ob_size && s != NULL; i++) {
  1443. X        if (i > 0)
  1444. X            joinstring(&s, comma);
  1445. X        t = reprobject(v->ob_item[i]);
  1446. X        joinstring(&s, t);
  1447. X        DECREF(t);
  1448. X    }
  1449. X    DECREF(comma);
  1450. X    t = newstringobject("]");
  1451. X    joinstring(&s, t);
  1452. X    DECREF(t);
  1453. X    return s;
  1454. X}
  1455. X
  1456. Xstatic int
  1457. Xlist_compare(v, w)
  1458. X    listobject *v, *w;
  1459. X{
  1460. X    int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
  1461. X    int i;
  1462. X    for (i = 0; i < len; i++) {
  1463. X        int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
  1464. X        if (cmp != 0)
  1465. X            return cmp;
  1466. X    }
  1467. X    return v->ob_size - w->ob_size;
  1468. X}
  1469. X
  1470. Xstatic int
  1471. Xlist_length(a)
  1472. X    listobject *a;
  1473. X{
  1474. X    return a->ob_size;
  1475. X}
  1476. X
  1477. Xstatic object *
  1478. Xlist_item(a, i)
  1479. X    listobject *a;
  1480. X    int i;
  1481. X{
  1482. X    if (i < 0 || i >= a->ob_size) {
  1483. X        err_setstr(IndexError, "list index out of range");
  1484. X        return NULL;
  1485. X    }
  1486. X    INCREF(a->ob_item[i]);
  1487. X    return a->ob_item[i];
  1488. X}
  1489. X
  1490. Xstatic object *
  1491. Xlist_slice(a, ilow, ihigh)
  1492. X    listobject *a;
  1493. X    int ilow, ihigh;
  1494. X{
  1495. X    listobject *np;
  1496. X    int i;
  1497. X    if (ilow < 0)
  1498. X        ilow = 0;
  1499. X    else if (ilow > a->ob_size)
  1500. X        ilow = a->ob_size;
  1501. X    if (ihigh < 0)
  1502. X        ihigh = 0;
  1503. X    if (ihigh < ilow)
  1504. X        ihigh = ilow;
  1505. X    else if (ihigh > a->ob_size)
  1506. X        ihigh = a->ob_size;
  1507. X    np = (listobject *) newlistobject(ihigh - ilow);
  1508. X    if (np == NULL)
  1509. X        return NULL;
  1510. X    for (i = ilow; i < ihigh; i++) {
  1511. X        object *v = a->ob_item[i];
  1512. X        INCREF(v);
  1513. X        np->ob_item[i - ilow] = v;
  1514. X    }
  1515. X    return (object *)np;
  1516. X}
  1517. X
  1518. Xstatic object *
  1519. Xlist_concat(a, bb)
  1520. X    listobject *a;
  1521. X    object *bb;
  1522. X{
  1523. X    int size;
  1524. X    int i;
  1525. X    listobject *np;
  1526. X    if (!is_listobject(bb)) {
  1527. X        err_badarg();
  1528. X        return NULL;
  1529. X    }
  1530. X#define b ((listobject *)bb)
  1531. X    size = a->ob_size + b->ob_size;
  1532. X    np = (listobject *) newlistobject(size);
  1533. X    if (np == NULL) {
  1534. X        return err_nomem();
  1535. X    }
  1536. X    for (i = 0; i < a->ob_size; i++) {
  1537. X        object *v = a->ob_item[i];
  1538. X        INCREF(v);
  1539. X        np->ob_item[i] = v;
  1540. X    }
  1541. X    for (i = 0; i < b->ob_size; i++) {
  1542. X        object *v = b->ob_item[i];
  1543. X        INCREF(v);
  1544. X        np->ob_item[i + a->ob_size] = v;
  1545. X    }
  1546. X    return (object *)np;
  1547. X#undef b
  1548. X}
  1549. X
  1550. Xstatic int
  1551. Xlist_ass_item(a, i, v)
  1552. X    listobject *a;
  1553. X    int i;
  1554. X    object *v;
  1555. X{
  1556. X    if (i < 0 || i >= a->ob_size) {
  1557. X        err_setstr(IndexError, "list assignment index out of range");
  1558. X        return -1;
  1559. X    }
  1560. X    if (v == NULL)
  1561. X        return list_ass_slice(a, i, i+1, v);
  1562. X    INCREF(v);
  1563. X    DECREF(a->ob_item[i]);
  1564. X    a->ob_item[i] = v;
  1565. X    return 0;
  1566. X}
  1567. X
  1568. Xstatic int
  1569. Xlist_ass_slice(a, ilow, ihigh, v)
  1570. X    listobject *a;
  1571. X    int ilow, ihigh;
  1572. X    object *v;
  1573. X{
  1574. X    object **item;
  1575. X    int n; /* Size of replacement list */
  1576. X    int d; /* Change in size */
  1577. X    int k; /* Loop index */
  1578. X#define b ((listobject *)v)
  1579. X    if (v == NULL)
  1580. X        n = 0;
  1581. X    else if (is_listobject(v))
  1582. X        n = b->ob_size;
  1583. X    else {
  1584. X        err_badarg();
  1585. X        return -1;
  1586. X    }
  1587. X    if (ilow < 0)
  1588. X        ilow = 0;
  1589. X    else if (ilow > a->ob_size)
  1590. X        ilow = a->ob_size;
  1591. X    if (ihigh < 0)
  1592. X        ihigh = 0;
  1593. X    if (ihigh < ilow)
  1594. X        ihigh = ilow;
  1595. X    else if (ihigh > a->ob_size)
  1596. X        ihigh = a->ob_size;
  1597. X    item = a->ob_item;
  1598. X    d = n - (ihigh-ilow);
  1599. X    if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
  1600. X        for (k = ilow; k < ihigh; k++)
  1601. X            DECREF(item[k]);
  1602. X        if (d < 0) {
  1603. X            for (/*k = ihigh*/; k < a->ob_size; k++)
  1604. X                item[k+d] = item[k];
  1605. X            a->ob_size += d;
  1606. X            RESIZE(item, object *, a->ob_size); /* Can't fail */
  1607. X            a->ob_item = item;
  1608. X        }
  1609. X    }
  1610. X    else { /* Insert d items; DECREF ihigh-ilow items */
  1611. X        RESIZE(item, object *, a->ob_size + d);
  1612. X        if (item == NULL) {
  1613. X            err_nomem();
  1614. X            return -1;
  1615. X        }
  1616. X        for (k = a->ob_size; --k >= ihigh; )
  1617. X            item[k+d] = item[k];
  1618. X        for (/*k = ihigh-1*/; k >= ilow; --k)
  1619. X            DECREF(item[k]);
  1620. X        a->ob_item = item;
  1621. X        a->ob_size += d;
  1622. X    }
  1623. X    for (k = 0; k < n; k++, ilow++) {
  1624. X        object *w = b->ob_item[k];
  1625. X        INCREF(w);
  1626. X        item[ilow] = w;
  1627. X    }
  1628. X    return 0;
  1629. X#undef b
  1630. X}
  1631. X
  1632. Xstatic object *
  1633. Xins(self, where, v)
  1634. X    listobject *self;
  1635. X    int where;
  1636. X    object *v;
  1637. X{
  1638. X    if (ins1(self, where, v) != 0)
  1639. X        return NULL;
  1640. X    INCREF(None);
  1641. X    return None;
  1642. X}
  1643. X
  1644. Xstatic object *
  1645. Xlistinsert(self, args)
  1646. X    listobject *self;
  1647. X    object *args;
  1648. X{
  1649. X    int i;
  1650. X    if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
  1651. X        err_badarg();
  1652. X        return NULL;
  1653. X    }
  1654. X    if (!getintarg(gettupleitem(args, 0), &i))
  1655. X        return NULL;
  1656. X    return ins(self, i, gettupleitem(args, 1));
  1657. X}
  1658. X
  1659. Xstatic object *
  1660. Xlistappend(self, args)
  1661. X    listobject *self;
  1662. X    object *args;
  1663. X{
  1664. X    return ins(self, (int) self->ob_size, args);
  1665. X}
  1666. X
  1667. Xstatic int
  1668. Xcmp(v, w)
  1669. X    char *v, *w;
  1670. X{
  1671. X    return cmpobject(* (object **) v, * (object **) w);
  1672. X}
  1673. X
  1674. Xstatic object *
  1675. Xlistsort(self, args)
  1676. X    listobject *self;
  1677. X    object *args;
  1678. X{
  1679. X    if (args != NULL) {
  1680. X        err_badarg();
  1681. X        return NULL;
  1682. X    }
  1683. X    err_clear();
  1684. X    if (self->ob_size > 1)
  1685. X        qsort((char *)self->ob_item,
  1686. X                (int) self->ob_size, sizeof(object *), cmp);
  1687. X    if (err_occurred())
  1688. X        return NULL;
  1689. X    INCREF(None);
  1690. X    return None;
  1691. X}
  1692. X
  1693. Xint
  1694. Xsortlist(v)
  1695. X    object *v;
  1696. X{
  1697. X    if (v == NULL || !is_listobject(v)) {
  1698. X        err_badcall();
  1699. X        return -1;
  1700. X    }
  1701. X    v = listsort((listobject *)v, (object *)NULL);
  1702. X    if (v == NULL)
  1703. X        return -1;
  1704. X    DECREF(v);
  1705. X    return 0;
  1706. X}
  1707. X
  1708. Xstatic struct methodlist list_methods[] = {
  1709. X    {"append",    listappend},
  1710. X    {"insert",    listinsert},
  1711. X    {"sort",    listsort},
  1712. X    {NULL,        NULL}        /* sentinel */
  1713. X};
  1714. X
  1715. Xstatic object *
  1716. Xlist_getattr(f, name)
  1717. X    listobject *f;
  1718. X    char *name;
  1719. X{
  1720. X    return findmethod(list_methods, (object *)f, name);
  1721. X}
  1722. X
  1723. Xstatic sequence_methods list_as_sequence = {
  1724. X    list_length,    /*sq_length*/
  1725. X    list_concat,    /*sq_concat*/
  1726. X    0,        /*sq_repeat*/
  1727. X    list_item,    /*sq_item*/
  1728. X    list_slice,    /*sq_slice*/
  1729. X    list_ass_item,    /*sq_ass_item*/
  1730. X    list_ass_slice,    /*sq_ass_slice*/
  1731. X};
  1732. X
  1733. Xtypeobject Listtype = {
  1734. X    OB_HEAD_INIT(&Typetype)
  1735. X    0,
  1736. X    "list",
  1737. X    sizeof(listobject),
  1738. X    0,
  1739. X    list_dealloc,    /*tp_dealloc*/
  1740. X    list_print,    /*tp_print*/
  1741. X    list_getattr,    /*tp_getattr*/
  1742. X    0,        /*tp_setattr*/
  1743. X    list_compare,    /*tp_compare*/
  1744. X    list_repr,    /*tp_repr*/
  1745. X    0,        /*tp_as_number*/
  1746. X    &list_as_sequence,    /*tp_as_sequence*/
  1747. X    0,        /*tp_as_mapping*/
  1748. X};
  1749. EOF
  1750. fi
  1751. if test -s 'src/parser.c'
  1752. then echo '*** I will not over-write existing file src/parser.c'
  1753. else
  1754. echo 'x - src/parser.c'
  1755. sed 's/^X//' > 'src/parser.c' << 'EOF'
  1756. X/***********************************************************
  1757. XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  1758. XNetherlands.
  1759. X
  1760. X                        All Rights Reserved
  1761. X
  1762. XPermission to use, copy, modify, and distribute this software and its 
  1763. Xdocumentation for any purpose and without fee is hereby granted, 
  1764. Xprovided that the above copyright notice appear in all copies and that
  1765. Xboth that copyright notice and this permission notice appear in 
  1766. Xsupporting documentation, and that the names of Stichting Mathematisch
  1767. XCentrum or CWI not be used in advertising or publicity pertaining to
  1768. Xdistribution of the software without specific, written prior permission.
  1769. X
  1770. XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1771. XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1772. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  1773. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1774. XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  1775. XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  1776. XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1777. X
  1778. X******************************************************************/
  1779. X
  1780. X/* Parser implementation */
  1781. X
  1782. X/* For a description, see the comments at end of this file */
  1783. X
  1784. X/* XXX To do: error recovery */
  1785. X
  1786. X#include "pgenheaders.h"
  1787. X#include "assert.h"
  1788. X#include "token.h"
  1789. X#include "grammar.h"
  1790. X#include "node.h"
  1791. X#include "parser.h"
  1792. X#include "errcode.h"
  1793. X
  1794. X
  1795. X#ifdef DEBUG
  1796. Xextern int debugging;
  1797. X#define D(x) if (!debugging); else x
  1798. X#else
  1799. X#define D(x)
  1800. X#endif
  1801. X
  1802. X
  1803. X/* STACK DATA TYPE */
  1804. X
  1805. Xstatic void s_reset PROTO((stack *));
  1806. X
  1807. Xstatic void
  1808. Xs_reset(s)
  1809. X    stack *s;
  1810. X{
  1811. X    s->s_top = &s->s_base[MAXSTACK];
  1812. X}
  1813. X
  1814. X#define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK])
  1815. X
  1816. Xstatic int s_push PROTO((stack *, dfa *, node *));
  1817. X
  1818. Xstatic int
  1819. Xs_push(s, d, parent)
  1820. X    register stack *s;
  1821. X    dfa *d;
  1822. X    node *parent;
  1823. X{
  1824. X    register stackentry *top;
  1825. X    if (s->s_top == s->s_base) {
  1826. X        fprintf(stderr, "s_push: parser stack overflow\n");
  1827. X        return -1;
  1828. X    }
  1829. X    top = --s->s_top;
  1830. X    top->s_dfa = d;
  1831. X    top->s_parent = parent;
  1832. X    top->s_state = 0;
  1833. X    return 0;
  1834. X}
  1835. X
  1836. X#ifdef DEBUG
  1837. X
  1838. Xstatic void s_pop PROTO((stack *));
  1839. X
  1840. Xstatic void
  1841. Xs_pop(s)
  1842. X    register stack *s;
  1843. X{
  1844. X    if (s_empty(s)) {
  1845. X        fprintf(stderr, "s_pop: parser stack underflow -- FATAL\n");
  1846. X        abort();
  1847. X    }
  1848. X    s->s_top++;
  1849. X}
  1850. X
  1851. X#else /* !DEBUG */
  1852. X
  1853. X#define s_pop(s) (s)->s_top++
  1854. X
  1855. X#endif
  1856. X
  1857. X
  1858. X/* PARSER CREATION */
  1859. X
  1860. Xparser_state *
  1861. Xnewparser(g, start)
  1862. X    grammar *g;
  1863. X    int start;
  1864. X{
  1865. X    parser_state *ps;
  1866. X    
  1867. X    if (!g->g_accel)
  1868. X        addaccelerators(g);
  1869. X    ps = NEW(parser_state, 1);
  1870. X    if (ps == NULL)
  1871. X        return NULL;
  1872. X    ps->p_grammar = g;
  1873. X    ps->p_tree = newtree(start);
  1874. X    if (ps->p_tree == NULL) {
  1875. X        DEL(ps);
  1876. X        return NULL;
  1877. X    }
  1878. X    s_reset(&ps->p_stack);
  1879. X    (void) s_push(&ps->p_stack, finddfa(g, start), ps->p_tree);
  1880. X    return ps;
  1881. X}
  1882. X
  1883. Xvoid
  1884. Xdelparser(ps)
  1885. X    parser_state *ps;
  1886. X{
  1887. X    /* NB If you want to save the parse tree,
  1888. X       you must set p_tree to NULL before calling delparser! */
  1889. X    freetree(ps->p_tree);
  1890. X    DEL(ps);
  1891. X}
  1892. X
  1893. X
  1894. X/* PARSER STACK OPERATIONS */
  1895. X
  1896. Xstatic int shift PROTO((stack *, int, char *, int, int));
  1897. X
  1898. Xstatic int
  1899. Xshift(s, type, str, newstate, lineno)
  1900. X    register stack *s;
  1901. X    int type;
  1902. X    char *str;
  1903. X    int newstate;
  1904. X    int lineno;
  1905. X{
  1906. X    assert(!s_empty(s));
  1907. X    if (addchild(s->s_top->s_parent, type, str, lineno) == NULL) {
  1908. X        fprintf(stderr, "shift: no mem in addchild\n");
  1909. X        return -1;
  1910. X    }
  1911. X    s->s_top->s_state = newstate;
  1912. X    return 0;
  1913. X}
  1914. X
  1915. Xstatic int push PROTO((stack *, int, dfa *, int, int));
  1916. X
  1917. Xstatic int
  1918. Xpush(s, type, d, newstate, lineno)
  1919. X    register stack *s;
  1920. X    int type;
  1921. X    dfa *d;
  1922. X    int newstate;
  1923. X    int lineno;
  1924. X{
  1925. X    register node *n;
  1926. X    n = s->s_top->s_parent;
  1927. X    assert(!s_empty(s));
  1928. X    if (addchild(n, type, (char *)NULL, lineno) == NULL) {
  1929. X        fprintf(stderr, "push: no mem in addchild\n");
  1930. X        return -1;
  1931. X    }
  1932. X    s->s_top->s_state = newstate;
  1933. X    return s_push(s, d, CHILD(n, NCH(n)-1));
  1934. X}
  1935. X
  1936. X
  1937. X/* PARSER PROPER */
  1938. X
  1939. Xstatic int classify PROTO((grammar *, int, char *));
  1940. X
  1941. Xstatic int
  1942. Xclassify(g, type, str)
  1943. X    grammar *g;
  1944. X    register int type;
  1945. X    char *str;
  1946. X{
  1947. X    register int n = g->g_ll.ll_nlabels;
  1948. X    
  1949. X    if (type == NAME) {
  1950. X        register char *s = str;
  1951. X        register label *l = g->g_ll.ll_label;
  1952. X        register int i;
  1953. X        for (i = n; i > 0; i--, l++) {
  1954. X            if (l->lb_type == NAME && l->lb_str != NULL &&
  1955. X                    l->lb_str[0] == s[0] &&
  1956. X                    strcmp(l->lb_str, s) == 0) {
  1957. X                D(printf("It's a keyword\n"));
  1958. X                return n - i;
  1959. X            }
  1960. X        }
  1961. X    }
  1962. X    
  1963. X    {
  1964. X        register label *l = g->g_ll.ll_label;
  1965. X        register int i;
  1966. X        for (i = n; i > 0; i--, l++) {
  1967. X            if (l->lb_type == type && l->lb_str == NULL) {
  1968. X                D(printf("It's a token we know\n"));
  1969. X                return n - i;
  1970. X            }
  1971. X        }
  1972. X    }
  1973. X    
  1974. X    D(printf("Illegal token\n"));
  1975. X    return -1;
  1976. X}
  1977. X
  1978. Xint
  1979. Xaddtoken(ps, type, str, lineno)
  1980. X    register parser_state *ps;
  1981. X    register int type;
  1982. X    char *str;
  1983. X    int lineno;
  1984. X{
  1985. X    register int ilabel;
  1986. X    
  1987. X    D(printf("Token %s/'%s' ... ", tok_name[type], str));
  1988. X    
  1989. X    /* Find out which label this token is */
  1990. X    ilabel = classify(ps->p_grammar, type, str);
  1991. X    if (ilabel < 0)
  1992. X        return E_SYNTAX;
  1993. X    
  1994. X    /* Loop until the token is shifted or an error occurred */
  1995. X    for (;;) {
  1996. X        /* Fetch the current dfa and state */
  1997. X        register dfa *d = ps->p_stack.s_top->s_dfa;
  1998. X        register state *s = &d->d_state[ps->p_stack.s_top->s_state];
  1999. X        
  2000. X        D(printf(" DFA '%s', state %d:",
  2001. X            d->d_name, ps->p_stack.s_top->s_state));
  2002. X        
  2003. X        /* Check accelerator */
  2004. X        if (s->s_lower <= ilabel && ilabel < s->s_upper) {
  2005. X            register int x = s->s_accel[ilabel - s->s_lower];
  2006. X            if (x != -1) {
  2007. X                if (x & (1<<7)) {
  2008. X                    /* Push non-terminal */
  2009. X                    int nt = (x >> 8) + NT_OFFSET;
  2010. X                    int arrow = x & ((1<<7)-1);
  2011. X                    dfa *d1 = finddfa(ps->p_grammar, nt);
  2012. X                    if (push(&ps->p_stack, nt, d1,
  2013. X                        arrow, lineno) < 0) {
  2014. X                        D(printf(" MemError: push.\n"));
  2015. X                        return E_NOMEM;
  2016. X                    }
  2017. X                    D(printf(" Push ...\n"));
  2018. X                    continue;
  2019. X                }
  2020. X                
  2021. X                /* Shift the token */
  2022. X                if (shift(&ps->p_stack, type, str,
  2023. X                        x, lineno) < 0) {
  2024. X                    D(printf(" MemError: shift.\n"));
  2025. X                    return E_NOMEM;
  2026. X                }
  2027. X                D(printf(" Shift.\n"));
  2028. X                /* Pop while we are in an accept-only state */
  2029. X                while (s = &d->d_state
  2030. X                        [ps->p_stack.s_top->s_state],
  2031. X                    s->s_accept && s->s_narcs == 1) {
  2032. X                    D(printf("  Direct pop.\n"));
  2033. X                    s_pop(&ps->p_stack);
  2034. X                    if (s_empty(&ps->p_stack)) {
  2035. X                        D(printf("  ACCEPT.\n"));
  2036. X                        return E_DONE;
  2037. X                    }
  2038. X                    d = ps->p_stack.s_top->s_dfa;
  2039. X                }
  2040. X                return E_OK;
  2041. X            }
  2042. X        }
  2043. X        
  2044. X        if (s->s_accept) {
  2045. X            /* Pop this dfa and try again */
  2046. X            s_pop(&ps->p_stack);
  2047. X            D(printf(" Pop ...\n"));
  2048. X            if (s_empty(&ps->p_stack)) {
  2049. X                D(printf(" Error: bottom of stack.\n"));
  2050. X                return E_SYNTAX;
  2051. X            }
  2052. X            continue;
  2053. X        }
  2054. X        
  2055. X        /* Stuck, report syntax error */
  2056. X        D(printf(" Error.\n"));
  2057. X        return E_SYNTAX;
  2058. X    }
  2059. X}
  2060. X
  2061. X
  2062. X#ifdef DEBUG
  2063. X
  2064. X/* DEBUG OUTPUT */
  2065. X
  2066. Xvoid
  2067. Xdumptree(g, n)
  2068. X    grammar *g;
  2069. X    node *n;
  2070. X{
  2071. X    int i;
  2072. X    
  2073. X    if (n == NULL)
  2074. X        printf("NIL");
  2075. X    else {
  2076. X        label l;
  2077. X        l.lb_type = TYPE(n);
  2078. X        l.lb_str = TYPE(str);
  2079. X        printf("%s", labelrepr(&l));
  2080. X        if (ISNONTERMINAL(TYPE(n))) {
  2081. X            printf("(");
  2082. X            for (i = 0; i < NCH(n); i++) {
  2083. X                if (i > 0)
  2084. X                    printf(",");
  2085. X                dumptree(g, CHILD(n, i));
  2086. X            }
  2087. X            printf(")");
  2088. X        }
  2089. X    }
  2090. X}
  2091. X
  2092. Xvoid
  2093. Xshowtree(g, n)
  2094. X    grammar *g;
  2095. X    node *n;
  2096. X{
  2097. X    int i;
  2098. X    
  2099. X    if (n == NULL)
  2100. X        return;
  2101. X    if (ISNONTERMINAL(TYPE(n))) {
  2102. X        for (i = 0; i < NCH(n); i++)
  2103. X            showtree(g, CHILD(n, i));
  2104. X    }
  2105. X    else if (ISTERMINAL(TYPE(n))) {
  2106. X        printf("%s", tok_name[TYPE(n)]);
  2107. X        if (TYPE(n) == NUMBER || TYPE(n) == NAME)
  2108. X            printf("(%s)", STR(n));
  2109. X        printf(" ");
  2110. X    }
  2111. X    else
  2112. X        printf("? ");
  2113. X}
  2114. X
  2115. Xvoid
  2116. Xprinttree(ps)
  2117. X    parser_state *ps;
  2118. X{
  2119. X    if (debugging) {
  2120. X        printf("Parse tree:\n");
  2121. X        dumptree(ps->p_grammar, ps->p_tree);
  2122. X        printf("\n");
  2123. X        printf("Tokens:\n");
  2124. X        showtree(ps->p_grammar, ps->p_tree);
  2125. X        printf("\n");
  2126. X    }
  2127. X    printf("Listing:\n");
  2128. X    listtree(ps->p_tree);
  2129. X    printf("\n");
  2130. X}
  2131. X
  2132. X#endif /* DEBUG */
  2133. X
  2134. X/*
  2135. X
  2136. XDescription
  2137. X-----------
  2138. X
  2139. XThe parser's interface is different than usual: the function addtoken()
  2140. Xmust be called for each token in the input.  This makes it possible to
  2141. Xturn it into an incremental parsing system later.  The parsing system
  2142. Xconstructs a parse tree as it goes.
  2143. X
  2144. XA parsing rule is represented as a Deterministic Finite-state Automaton
  2145. X(DFA).  A node in a DFA represents a state of the parser; an arc represents
  2146. Xa transition.  Transitions are either labeled with terminal symbols or
  2147. Xwith non-terminals.  When the parser decides to follow an arc labeled
  2148. Xwith a non-terminal, it is invoked recursively with the DFA representing
  2149. Xthe parsing rule for that as its initial state; when that DFA accepts,
  2150. Xthe parser that invoked it continues.  The parse tree constructed by the
  2151. Xrecursively called parser is inserted as a child in the current parse tree.
  2152. X
  2153. XThe DFA's can be constructed automatically from a more conventional
  2154. Xlanguage description.  An extended LL(1) grammar (ELL(1)) is suitable.
  2155. XCertain restrictions make the parser's life easier: rules that can produce
  2156. Xthe empty string should be outlawed (there are other ways to put loops
  2157. Xor optional parts in the language).  To avoid the need to construct
  2158. XFIRST sets, we can require that all but the last alternative of a rule
  2159. X(really: arc going out of a DFA's state) must begin with a terminal
  2160. Xsymbol.
  2161. X
  2162. XAs an example, consider this grammar:
  2163. X
  2164. Xexpr:    term (OP term)*
  2165. Xterm:    CONSTANT | '(' expr ')'
  2166. X
  2167. XThe DFA corresponding to the rule for expr is:
  2168. X
  2169. X------->.---term-->.------->
  2170. X    ^          |
  2171. X    |          |
  2172. X    \----OP----/
  2173. X
  2174. XThe parse tree generated for the input a+b is:
  2175. X
  2176. X(expr: (term: (NAME: a)), (OP: +), (term: (NAME: b)))
  2177. X
  2178. X*/
  2179. EOF
  2180. fi
  2181. if test -s 'src/patchlevel.h'
  2182. then echo '*** I will not over-write existing file src/patchlevel.h'
  2183. else
  2184. echo 'x - src/patchlevel.h'
  2185. sed 's/^X//' > 'src/patchlevel.h' << 'EOF'
  2186. X1
  2187. EOF
  2188. fi
  2189. if test -s 'src/posixmodule.c'
  2190. then echo '*** I will not over-write existing file src/posixmodule.c'
  2191. else
  2192. echo 'x - src/posixmodule.c'
  2193. sed 's/^X//' > 'src/posixmodule.c' << 'EOF'
  2194. X/***********************************************************
  2195. XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  2196. XNetherlands.
  2197. X
  2198. X                        All Rights Reserved
  2199. X
  2200. XPermission to use, copy, modify, and distribute this software and its 
  2201. Xdocumentation for any purpose and without fee is hereby granted, 
  2202. Xprovided that the above copyright notice appear in all copies and that
  2203. Xboth that copyright notice and this permission notice appear in 
  2204. Xsupporting documentation, and that the names of Stichting Mathematisch
  2205. XCentrum or CWI not be used in advertising or publicity pertaining to
  2206. Xdistribution of the software without specific, written prior permission.
  2207. X
  2208. XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  2209. XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  2210. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  2211. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  2212. XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  2213. XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  2214. XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  2215. X
  2216. X******************************************************************/
  2217. X
  2218. X/* POSIX module implementation */
  2219. X
  2220. X#include <signal.h>
  2221. X#include <string.h>
  2222. X#include <setjmp.h>
  2223. X#include <sys/types.h>
  2224. X#include <sys/stat.h>
  2225. X#include <sys/time.h>
  2226. X#ifdef SYSV
  2227. X#include <dirent.h>
  2228. X#define direct dirent
  2229. X#else
  2230. X#include <sys/dir.h>
  2231. X#endif
  2232. X
  2233. X#include "allobjects.h"
  2234. X#include "modsupport.h"
  2235. X
  2236. Xextern char *strerror PROTO((int));
  2237. X
  2238. X#ifdef AMOEBA
  2239. X#define NO_LSTAT
  2240. X#endif
  2241. X
  2242. X
  2243. X/* Return a dictionary corresponding to the POSIX environment table */
  2244. X
  2245. Xextern char **environ;
  2246. X
  2247. Xstatic object *
  2248. Xconvertenviron()
  2249. X{
  2250. X    object *d;
  2251. X    char **e;
  2252. X    d = newdictobject();
  2253. X    if (d == NULL)
  2254. X        return NULL;
  2255. X    if (environ == NULL)
  2256. X        return d;
  2257. X    /* XXX This part ignores errors */
  2258. X    for (e = environ; *e != NULL; e++) {
  2259. X        object *v;
  2260. X        char *p = strchr(*e, '=');
  2261. X        if (p == NULL)
  2262. X            continue;
  2263. X        v = newstringobject(p+1);
  2264. X        if (v == NULL)
  2265. X            continue;
  2266. X        *p = '\0';
  2267. X        (void) dictinsert(d, *e, v);
  2268. X        *p = '=';
  2269. X        DECREF(v);
  2270. X    }
  2271. X    return d;
  2272. X}
  2273. X
  2274. X
  2275. Xstatic object *PosixError; /* Exception posix.error */
  2276. X
  2277. X/* Set a POSIX-specific error from errno, and return NULL */
  2278. X
  2279. Xstatic object *
  2280. Xposix_error()
  2281. X{
  2282. X    return err_errno(PosixError);
  2283. X}
  2284. X
  2285. X
  2286. X/* POSIX generic methods */
  2287. X
  2288. Xstatic object *
  2289. Xposix_1str(args, func)
  2290. X    object *args;
  2291. X    int (*func) FPROTO((const char *));
  2292. X{
  2293. X    object *path1;
  2294. X    if (!getstrarg(args, &path1))
  2295. X        return NULL;
  2296. X    if ((*func)(getstringvalue(path1)) < 0)
  2297. X        return posix_error();
  2298. X    INCREF(None);
  2299. X    return None;
  2300. X}
  2301. X
  2302. Xstatic object *
  2303. Xposix_2str(args, func)
  2304. X    object *args;
  2305. X    int (*func) FPROTO((const char *, const char *));
  2306. X{
  2307. X    object *path1, *path2;
  2308. X    if (!getstrstrarg(args, &path1, &path2))
  2309. X        return NULL;
  2310. X    if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
  2311. X        return posix_error();
  2312. X    INCREF(None);
  2313. X    return None;
  2314. X}
  2315. X
  2316. Xstatic object *
  2317. Xposix_strint(args, func)
  2318. X    object *args;
  2319. X    int (*func) FPROTO((const char *, int));
  2320. X{
  2321. X    object *path1;
  2322. X    int i;
  2323. X    if (!getstrintarg(args, &path1, &i))
  2324. X        return NULL;
  2325. X    if ((*func)(getstringvalue(path1), i) < 0)
  2326. X        return posix_error();
  2327. X    INCREF(None);
  2328. X    return None;
  2329. X}
  2330. X
  2331. Xstatic object *
  2332. Xposix_do_stat(self, args, statfunc)
  2333. X    object *self;
  2334. X    object *args;
  2335. X    int (*statfunc) FPROTO((const char *, struct stat *));
  2336. X{
  2337. X    struct stat st;
  2338. X    object *path;
  2339. X    object *v;
  2340. X    if (!getstrarg(args, &path))
  2341. X        return NULL;
  2342. X    if ((*statfunc)(getstringvalue(path), &st) != 0)
  2343. X        return posix_error();
  2344. X    v = newtupleobject(10);
  2345. X    if (v == NULL)
  2346. X        return NULL;
  2347. X#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
  2348. X    SET(0, st_mode);
  2349. X    SET(1, st_ino);
  2350. X    SET(2, st_dev);
  2351. X    SET(3, st_nlink);
  2352. X    SET(4, st_uid);
  2353. X    SET(5, st_gid);
  2354. X    SET(6, st_size);
  2355. X    SET(7, st_atime);
  2356. X    SET(8, st_mtime);
  2357. X    SET(9, st_ctime);
  2358. X#undef SET
  2359. X    if (err_occurred()) {
  2360. X        DECREF(v);
  2361. X        return NULL;
  2362. X    }
  2363. X    return v;
  2364. X}
  2365. X
  2366. X
  2367. X/* POSIX methods */
  2368. X
  2369. Xstatic object *
  2370. Xposix_chdir(self, args)
  2371. X    object *self;
  2372. X    object *args;
  2373. X{
  2374. X    extern int chdir PROTO((const char *));
  2375. X    return posix_1str(args, chdir);
  2376. X}
  2377. X
  2378. Xstatic object *
  2379. Xposix_chmod(self, args)
  2380. X    object *self;
  2381. X    object *args;
  2382. X{
  2383. X    extern int chmod PROTO((const char *, mode_t));
  2384. X    return posix_strint(args, chmod);
  2385. X}
  2386. X
  2387. Xstatic object *
  2388. Xposix_getcwd(self, args)
  2389. X    object *self;
  2390. X    object *args;
  2391. X{
  2392. X    char buf[1026];
  2393. X    extern char *getcwd PROTO((char *, int));
  2394. X    if (!getnoarg(args))
  2395. X        return NULL;
  2396. X    if (getcwd(buf, sizeof buf) == NULL)
  2397. X        return posix_error();
  2398. X    return newstringobject(buf);
  2399. X}
  2400. X
  2401. Xstatic object *
  2402. Xposix_link(self, args)
  2403. X    object *self;
  2404. X    object *args;
  2405. X{
  2406. X    extern int link PROTO((const char *, const char *));
  2407. X    return posix_2str(args, link);
  2408. X}
  2409. X
  2410. Xstatic object *
  2411. Xposix_listdir(self, args)
  2412. X    object *self;
  2413. X    object *args;
  2414. X{
  2415. X    object *name, *d, *v;
  2416. X    DIR *dirp;
  2417. X    struct direct *ep;
  2418. X    if (!getstrarg(args, &name))
  2419. X        return NULL;
  2420. X    if ((dirp = opendir(getstringvalue(name))) == NULL)
  2421. X        return posix_error();
  2422. X    if ((d = newlistobject(0)) == NULL) {
  2423. X        closedir(dirp);
  2424. X        return NULL;
  2425. X    }
  2426. X    while ((ep = readdir(dirp)) != NULL) {
  2427. X        v = newstringobject(ep->d_name);
  2428. X        if (v == NULL) {
  2429. X            DECREF(d);
  2430. X            d = NULL;
  2431. X            break;
  2432. X        }
  2433. X        if (addlistitem(d, v) != 0) {
  2434. X            DECREF(v);
  2435. X            DECREF(d);
  2436. X            d = NULL;
  2437. X            break;
  2438. X        }
  2439. X        DECREF(v);
  2440. X    }
  2441. X    closedir(dirp);
  2442. X    return d;
  2443. X}
  2444. X
  2445. Xstatic object *
  2446. Xposix_mkdir(self, args)
  2447. X    object *self;
  2448. X    object *args;
  2449. X{
  2450. X    extern int mkdir PROTO((const char *, mode_t));
  2451. X    return posix_strint(args, mkdir);
  2452. X}
  2453. X
  2454. Xstatic object *
  2455. Xposix_rename(self, args)
  2456. X    object *self;
  2457. X    object *args;
  2458. X{
  2459. X    extern int rename PROTO((const char *, const char *));
  2460. X    return posix_2str(args, rename);
  2461. X}
  2462. X
  2463. Xstatic object *
  2464. Xposix_rmdir(self, args)
  2465. X    object *self;
  2466. X    object *args;
  2467. X{
  2468. X    extern int rmdir PROTO((const char *));
  2469. X    return posix_1str(args, rmdir);
  2470. X}
  2471. X
  2472. Xstatic object *
  2473. Xposix_stat(self, args)
  2474. X    object *self;
  2475. X    object *args;
  2476. X{
  2477. X    extern int stat PROTO((const char *, struct stat *));
  2478. X    return posix_do_stat(self, args, stat);
  2479. X}
  2480. X
  2481. Xstatic object *
  2482. Xposix_system(self, args)
  2483. X    object *self;
  2484. X    object *args;
  2485. X{
  2486. X    object *command;
  2487. X    int sts;
  2488. X    if (!getstrarg(args, &command))
  2489. X        return NULL;
  2490. X    sts = system(getstringvalue(command));
  2491. X    return newintobject((long)sts);
  2492. X}
  2493. X
  2494. Xstatic object *
  2495. Xposix_umask(self, args)
  2496. X    object *self;
  2497. X    object *args;
  2498. X{
  2499. X    int i;
  2500. X    if (!getintarg(args, &i))
  2501. X        return NULL;
  2502. X    i = umask(i);
  2503. X    if (i < 0)
  2504. X        return posix_error();
  2505. X    return newintobject((long)i);
  2506. X}
  2507. X
  2508. Xstatic object *
  2509. Xposix_unlink(self, args)
  2510. X    object *self;
  2511. X    object *args;
  2512. X{
  2513. X    extern int unlink PROTO((const char *));
  2514. X    return posix_1str(args, unlink);
  2515. X}
  2516. X
  2517. Xstatic object *
  2518. Xposix_utimes(self, args)
  2519. X    object *self;
  2520. X    object *args;
  2521. X{
  2522. X    object *path;
  2523. X    struct timeval tv[2];
  2524. X    if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
  2525. X        err_badarg();
  2526. X        return NULL;
  2527. X    }
  2528. X    if (!getstrarg(gettupleitem(args, 0), &path) ||
  2529. X                !getlonglongargs(gettupleitem(args, 1),
  2530. X                    &tv[0].tv_sec, &tv[1].tv_sec))
  2531. X        return NULL;
  2532. X    tv[0].tv_usec = tv[1].tv_usec = 0;
  2533. X    if (utimes(getstringvalue(path), tv) < 0)
  2534. X        return posix_error();
  2535. X    INCREF(None);
  2536. X    return None;
  2537. X}
  2538. X
  2539. X
  2540. X#ifndef NO_LSTAT
  2541. X
  2542. Xstatic object *
  2543. Xposix_lstat(self, args)
  2544. X    object *self;
  2545. X    object *args;
  2546. X{
  2547. X    extern int lstat PROTO((const char *, struct stat *));
  2548. X    return posix_do_stat(self, args, lstat);
  2549. X}
  2550. X
  2551. Xstatic object *
  2552. Xposix_readlink(self, args)
  2553. X    object *self;
  2554. X    object *args;
  2555. X{
  2556. X    char buf[1024]; /* XXX Should use MAXPATHLEN */
  2557. X    object *path;
  2558. X    int n;
  2559. X    if (!getstrarg(args, &path))
  2560. X        return NULL;
  2561. X    n = readlink(getstringvalue(path), buf, sizeof buf);
  2562. X    if (n < 0)
  2563. X        return posix_error();
  2564. X    return newsizedstringobject(buf, n);
  2565. X}
  2566. X
  2567. Xstatic object *
  2568. Xposix_symlink(self, args)
  2569. X    object *self;
  2570. X    object *args;
  2571. X{
  2572. X    extern int symlink PROTO((const char *, const char *));
  2573. X    return posix_2str(args, symlink);
  2574. X}
  2575. X
  2576. X#endif /* NO_LSTAT */
  2577. X
  2578. X
  2579. Xstatic struct methodlist posix_methods[] = {
  2580. X    {"chdir",    posix_chdir},
  2581. X    {"chmod",    posix_chmod},
  2582. X    {"getcwd",    posix_getcwd},
  2583. X    {"link",    posix_link},
  2584. X    {"listdir",    posix_listdir},
  2585. X    {"mkdir",    posix_mkdir},
  2586. X    {"rename",    posix_rename},
  2587. X    {"rmdir",    posix_rmdir},
  2588. X    {"stat",    posix_stat},
  2589. X    {"system",    posix_system},
  2590. X    {"umask",    posix_umask},
  2591. X    {"unlink",    posix_unlink},
  2592. X    {"utimes",    posix_utimes},
  2593. X#ifndef NO_LSTAT
  2594. X    {"lstat",    posix_lstat},
  2595. X    {"readlink",    posix_readlink},
  2596. X    {"symlink",    posix_symlink},
  2597. X#endif
  2598. X    {NULL,        NULL}         /* Sentinel */
  2599. X};
  2600. X
  2601. X
  2602. Xvoid
  2603. Xinitposix()
  2604. X{
  2605. X    object *m, *d, *v;
  2606. X    
  2607. X    m = initmodule("posix", posix_methods);
  2608. X    d = getmoduledict(m);
  2609. X    
  2610. X    /* Initialize posix.environ dictionary */
  2611. X    v = convertenviron();
  2612. X    if (v == NULL || dictinsert(d, "environ", v) != 0)
  2613. X        fatal("can't define posix.environ");
  2614. X    DECREF(v);
  2615. X    
  2616. X    /* Initialize posix.error exception */
  2617. X    PosixError = newstringobject("posix.error");
  2618. X    if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  2619. X        fatal("can't define posix.error");
  2620. X}
  2621. EOF
  2622. fi
  2623. echo 'Part 11 out of 21 of pack.out complete.'
  2624. exit 0
  2625.