home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2802 < 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 10/21
  4. Message-ID: <2972@charon.cwi.nl>
  5. Date: 19 Feb 91 17:41:58 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 10 out of 21:'
  12. if test -s 'demo/sgi/gl_panel/flying/light.py'
  13. then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/light.py'
  14. else
  15. echo 'x - demo/sgi/gl_panel/flying/light.py'
  16. sed 's/^X//' > 'demo/sgi/gl_panel/flying/light.py' << 'EOF'
  17. Xfrom GL import *
  18. Xfrom gl import *
  19. X
  20. X# identity matrix
  21. Xidmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
  22. X
  23. X# the different materials.
  24. Xm1=[SPECULAR,0.8,0.0,0.0,DIFFUSE,0.4,0.0,0.0,SHININESS,40.0,LMNULL]
  25. Xm2=[SPECULAR,1.0,0.4,0.0,DIFFUSE,1.0,0.4,0.0,SHININESS,80.0,LMNULL]
  26. Xm3=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,60.0,LMNULL]
  27. Xm4=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
  28. Xm5=[SPECULAR,1.0,1.0,0.0,DIFFUSE,0.6,0.6,0.0,SHININESS,100.0,LMNULL]
  29. Xm6=[SPECULAR,1.0,0.0,1.0,DIFFUSE,0.6,0.0,0.6,SHININESS,120.0,LMNULL]
  30. Xm7=[SPECULAR,0.9,0.9,0.9,DIFFUSE,0.6,0.6,0.6,SHININESS,120.0,LMNULL]
  31. Xm8=[SPECULAR,0.4,0.7,0.4,DIFFUSE,0.5,1.0,0.5,SHININESS,50.0,LMNULL]
  32. Xm9=[SPECULAR,0.2,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,10.0,LMNULL]
  33. X
  34. X#the lightsources.
  35. Xlight1 = [LCOLOR,1.0,1.0,1.0,POSITION,10.0,10.0,5.0,0.0,LMNULL]
  36. Xlight2 = [LCOLOR,1.0,1.0,1.0,POSITION,-10.0,10.0,5.0,0.0,LMNULL]
  37. X
  38. X# the lightmodel.
  39. Xmodel = [AMBIENT,0.4,0.4,0.4,LMNULL]
  40. X
  41. Xdef bindlight (bool) :
  42. X    # Initializes all settings for a window.
  43. X    if bool <> 0 :
  44. X        mmode(MVIEWING)
  45. X        perspective (900, 1.0, 1.0, 35.0)
  46. X        loadmatrix(idmat)
  47. X    # define materials and lights
  48. X    lmdef(DEFMATERIAL, 1, m1)
  49. X    lmdef(DEFMATERIAL, 2, m2)
  50. X    lmdef(DEFMATERIAL, 3, m3)
  51. X    lmdef(DEFMATERIAL, 4, m4)
  52. X    lmdef(DEFMATERIAL, 5, m5)
  53. X    lmdef(DEFMATERIAL, 6, m6)
  54. X    lmdef(DEFMATERIAL, 7, m7)
  55. X    lmdef(DEFMATERIAL, 8, m8)
  56. X    lmdef(DEFMATERIAL, 9, m9)
  57. X    lmdef(DEFLIGHT, 1, light1)
  58. X    lmdef(DEFLIGHT, 2, light2)
  59. X    lmdef(DEFLMODEL, 1, model)
  60. X    lmbind(LIGHT0,1)
  61. X    lmbind(LIGHT1,2)
  62. X    lmbind(LMODEL,1)
  63. EOF
  64. fi
  65. if test -s 'demo/stdwin/wdiff.py'
  66. then echo '*** I will not over-write existing file demo/stdwin/wdiff.py'
  67. else
  68. echo 'x - demo/stdwin/wdiff.py'
  69. sed 's/^X//' > 'demo/stdwin/wdiff.py' << 'EOF'
  70. X#! /ufs/guido/bin/sgi/python
  71. X
  72. X# A window-oriented recursive diff utility.
  73. X# NB: This uses undocumented window classing modules.
  74. X
  75. X# TO DO:
  76. X#    - faster update after moving/copying one file
  77. X#    - diff flags (-b, etc.) should be global or maintained per window
  78. X#    - use a few fixed windows instead of creating new ones all the time
  79. X#    - ways to specify patterns to skip
  80. X#      (best by pointing at a file and clicking a special menu entry!)
  81. X#    - add rcsdiff menu commands
  82. X#    - add a way to view status of selected files without opening them
  83. X#    - add a way to diff two files with different names
  84. X#    - add a way to rename files
  85. X#    - keep backups of overwritten/deleted files
  86. X#    - a way to mark specified files as uninteresting for dircmp
  87. X
  88. Ximport sys
  89. Ximport posix
  90. Ximport path
  91. Ximport rand
  92. Ximport commands
  93. Ximport dircache
  94. Ximport statcache
  95. Ximport cmp
  96. Ximport cmpcache
  97. Ximport stdwin
  98. Ximport gwin
  99. Ximport textwin
  100. Ximport filewin
  101. Ximport tablewin
  102. Ximport anywin
  103. X
  104. Xmkarg = commands.mkarg
  105. Xmk2arg = commands.mk2arg
  106. X
  107. X# List of names to ignore in dircmp()
  108. X# (Should be done with function, so we can specify patterns as well)
  109. X#
  110. Xskiplist = ['RCS', '.Amake', 'tags', '.', '..']
  111. X
  112. X
  113. Xdef anydiff(a, b, flags): # Display differences between any two objects
  114. X    print 'diff', flags, a, b
  115. X    if path.isdir(a) and path.isdir(b):
  116. X        w = dirdiff(a, b, flags)
  117. X    else:
  118. X        w = filediff(a, b, flags)
  119. X    addstatmenu(w, [a, b])
  120. X    w.original_close = w.close
  121. X    w.close = close_dirwin
  122. X    return w
  123. X
  124. Xdef close_dirwin(w):
  125. X    close_subwindows(w, (), 0)
  126. X    w.original_close(w)
  127. X
  128. Xdef filediff(a, b, flags): # Display differences between two text files
  129. X    diffcmd = 'diff'
  130. X    if flags: diffcmd = diffcmd + mkarg(flags)
  131. X    diffcmd = diffcmd + mkarg(a) + mkarg(b)
  132. X    difftext = commands.getoutput(diffcmd)
  133. X    return textwin.open_readonly(mktitle(a, b), difftext)
  134. X
  135. Xdef dirdiff(a, b, flags): # Display differences between two directories
  136. X    data = diffdata(a, b, flags)
  137. X    w = tablewin.open(mktitle(a, b), data)
  138. X    w.flags = flags
  139. X    w.a = a
  140. X    w.b = b
  141. X    addviewmenu(w)
  142. X    addactionmenu(w)
  143. X    return w
  144. X
  145. Xdef diffdata(a, b, flags): # Compute directory differences.
  146. X    #
  147. X    a_only = [('A only:', header_action), ('', header_action)]
  148. X    b_only = [('B only:', header_action), ('', header_action)]
  149. X    ab_diff = [('A <> B:', header_action), ('', header_action)]
  150. X    ab_same = [('A == B:', header_action), ('', header_action)]
  151. X    data = [a_only, b_only, ab_diff, ab_same]
  152. X    #
  153. X    a_list = dircache.listdir(a)[:]
  154. X    b_list = dircache.listdir(b)[:]
  155. X    dircache.annotate(a, a_list)
  156. X    dircache.annotate(b, b_list)
  157. X    a_list.sort()
  158. X    b_list.sort()
  159. X    #
  160. X    for x in a_list:
  161. X        if x in ['./', '../']:
  162. X            pass
  163. X        elif x not in b_list:
  164. X            a_only.append(x, a_only_action)
  165. X        else:
  166. X            ax = path.cat(a, x)
  167. X            bx = path.cat(b, x)
  168. X            if path.isdir(ax) and path.isdir(bx):
  169. X                if flags = '-r':
  170. X                    same = dircmp(ax, bx)
  171. X                else:
  172. X                    same = 0
  173. X            else:
  174. X                try:
  175. X                    same = cmp.cmp(ax, bx)
  176. X                except posix.error:
  177. X                    same = 0
  178. X            if same:
  179. X                ab_same.append(x, ab_same_action)
  180. X            else:
  181. X                ab_diff.append(x, ab_diff_action)
  182. X    #
  183. X    for x in b_list:
  184. X        if x in ['./', '../']:
  185. X            pass
  186. X        elif x not in a_list:
  187. X            b_only.append(x, b_only_action)
  188. X    #
  189. X    return data
  190. X
  191. X# Re-read the directory.
  192. X# Attempt to find the selected item back.
  193. X
  194. Xdef update(w):
  195. X    setbusy(w)
  196. X    icol, irow = w.selection
  197. X    if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]):
  198. X        selname = w.data[icol][irow][0]
  199. X    else:
  200. X        selname = ''
  201. X    statcache.forget_dir(w.a)
  202. X    statcache.forget_dir(w.b)
  203. X    tablewin.select(w, (-1, -1))
  204. X    tablewin.update(w, diffdata(w.a, w.b, w.flags))
  205. X    if selname:
  206. X        for icol in range(len(w.data)):
  207. X            for irow in range(2, len(w.data[icol])):
  208. X                if w.data[icol][irow][0] = selname:
  209. X                    tablewin.select(w, (icol, irow))
  210. X                    break
  211. X
  212. X# Action functions for table items in directory diff windows
  213. X
  214. Xdef header_action(w, string, (icol, irow), (pos, clicks, button, mask)):
  215. X    tablewin.select(w, (-1, -1))
  216. X
  217. Xdef a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
  218. X    tablewin.select(w, (icol, irow))
  219. X    if clicks = 2:
  220. X        w2 = anyopen(path.cat(w.a, string))
  221. X        if w2:
  222. X            w2.parent = w
  223. X
  224. Xdef b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
  225. X    tablewin.select(w, (icol, irow))
  226. X    if clicks = 2:
  227. X        w2 = anyopen(path.cat(w.b, string))
  228. X        if w2:
  229. X            w2.parent = w
  230. X
  231. Xdef ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)):
  232. X    tablewin.select(w, (icol, irow))
  233. X    if clicks = 2:
  234. X        w2 = anydiff(path.cat(w.a, string), path.cat(w.b, string), '')
  235. X        w2.parent = w
  236. X
  237. Xdef ab_same_action(w, string, sel, detail):
  238. X    ax = path.cat(w.a, string)
  239. X    if path.isdir(ax):
  240. X        ab_diff_action(w, string, sel, detail)
  241. X    else:
  242. X        a_only_action(w, string, sel, detail)
  243. X
  244. Xdef anyopen(name): # Open any kind of document, ignore errors
  245. X    try:
  246. X        w = anywin.open(name)
  247. X    except (RuntimeError, posix.error):
  248. X        stdwin.message('Can\'t open ' + name)
  249. X        return 0
  250. X    addstatmenu(w, [name])
  251. X    return w
  252. X
  253. Xdef dircmp(a, b): # Compare whether two directories are the same
  254. X    # To make this as fast as possible, it uses the statcache
  255. X    print '  dircmp', a, b
  256. X    a_list = dircache.listdir(a)
  257. X    b_list = dircache.listdir(b)
  258. X    for x in a_list:
  259. X        if x in skiplist:
  260. X            pass
  261. X        elif x not in b_list:
  262. X            return 0
  263. X        else:
  264. X            ax = path.cat(a, x)
  265. X            bx = path.cat(b, x)
  266. X            if statcache.isdir(ax) and statcache.isdir(bx):
  267. X                if not dircmp(ax, bx): return 0
  268. X            else:
  269. X                try:
  270. X                    if not cmpcache.cmp(ax, bx): return 0
  271. X                except posix.error:
  272. X                    return 0
  273. X    for x in b_list:
  274. X        if x in skiplist:
  275. X            pass
  276. X        elif x not in a_list:
  277. X            return 0
  278. X    return 1
  279. X
  280. X
  281. X# View menu (for dir diff windows only)
  282. X
  283. Xdef addviewmenu(w):
  284. X    w.viewmenu = m = w.menucreate('View')
  285. X    m.action = []
  286. X    add(m, 'diff -r A B', diffr_ab)
  287. X    add(m, 'diff A B', diff_ab)
  288. X    add(m, 'diff -b A B', diffb_ab)
  289. X    add(m, 'diff -c A B', diffc_ab)
  290. X    add(m, 'gdiff A B', gdiff_ab)
  291. X    add(m, ('Open A   ', 'A'), open_a)
  292. X    add(m, ('Open B   ', 'B'), open_b)
  293. X    add(m, 'Rescan', rescan)
  294. X    add(m, 'Rescan -r', rescan_r)
  295. X
  296. X# Action menu (for dir diff windows only)
  297. X
  298. Xdef addactionmenu(w):
  299. X    w.actionmenu = m = w.menucreate('Action')
  300. X    m.action = []
  301. X    add(m, 'cp A B', cp_ab)
  302. X    add(m, 'rm B', rm_b)
  303. X    add(m, '', nop)
  304. X    add(m, 'cp B A', cp_ba)
  305. X    add(m, 'rm A', rm_a)
  306. X
  307. X# Main menu (global):
  308. X
  309. Xdef mainmenu():
  310. X    m = stdwin.menucreate('Wdiff')
  311. X    m.action = []
  312. X    add(m, ('Quit wdiff', 'Q'), quit_wdiff)
  313. X    add(m, 'Close subwindows', close_subwindows)
  314. X    return m
  315. X
  316. Xdef add(m, text, action):
  317. X    m.additem(text)
  318. X    m.action.append(action)
  319. X
  320. Xdef quit_wdiff(w, m, item):
  321. X    if askyesno('Really quit wdiff altogether?', 1):
  322. X        sys.exit(0)
  323. X
  324. Xdef close_subwindows(w, m, item):
  325. X    while 1:
  326. X        for w2 in gwin.windows:
  327. X            if w2.parent = w:
  328. X                close_subwindows(w2, m, item)
  329. X                w2.close(w2)
  330. X                break # inner loop, continue outer loop
  331. X        else:
  332. X            break # outer loop
  333. X
  334. Xdef diffr_ab(w, m, item):
  335. X    dodiff(w, '-r')
  336. X
  337. Xdef diff_ab(w, m, item):
  338. X    dodiff(w, '')
  339. X
  340. Xdef diffb_ab(w, m, item):
  341. X    dodiff(w, '-b')
  342. X
  343. Xdef diffc_ab(w, m, item):
  344. X    dodiff(w, '-c')
  345. X
  346. Xdef gdiff_ab(w, m, item): # Call SGI's gdiff utility
  347. X    x = getselection(w)
  348. X    if x:
  349. X        a, b = path.cat(w.a, x), path.cat(w.b, x)
  350. X        if path.isdir(a) or path.isdir(b):
  351. X            stdwin.fleep() # This is for files only
  352. X        else:
  353. X            diffcmd = 'gdiff'
  354. X            diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &'
  355. X            print diffcmd
  356. X            sts = posix.system(diffcmd)
  357. X            if sts: print 'Exit status', sts
  358. X
  359. Xdef dodiff(w, flags):
  360. X    x = getselection(w)
  361. X    if x:
  362. X        w2 = anydiff(path.cat(w.a, x), path.cat(w.b, x), flags)
  363. X        w2.parent = w
  364. X
  365. Xdef open_a(w, m, item):
  366. X    x = getselection(w)
  367. X    if x:
  368. X        w2 = anyopen(path.cat(w.a, x))
  369. X        if w2:
  370. X            w2.parent = w
  371. X
  372. Xdef open_b(w, m, item):
  373. X    x = getselection(w)
  374. X    if x:
  375. X        w2 = anyopen(path.cat(w.b, x))
  376. X        if w2:
  377. X            w2.parent = w
  378. X
  379. Xdef rescan(w, m, item):
  380. X    w.flags = ''
  381. X    update(w)
  382. X
  383. Xdef rescan_r(w, m, item):
  384. X    w.flags = '-r'
  385. X    update(w)
  386. X
  387. Xdef rm_a(w, m, item):
  388. X    x = getselection(w)
  389. X    if x:
  390. X        if x[-1:] = '/': x = x[:-1]
  391. X        x = path.cat(w.a, x)
  392. X        if path.isdir(x):
  393. X            if askyesno('Recursively remove A directory ' + x, 1):
  394. X                runcmd('rm -rf' + mkarg(x))
  395. X        else:
  396. X            runcmd('rm -f' + mkarg(x))
  397. X        update(w)
  398. X
  399. Xdef rm_b(w, m, item):
  400. X    x = getselection(w)
  401. X    if x:
  402. X        if x[-1:] = '/': x = x[:-1]
  403. X        x = path.cat(w.b, x)
  404. X        if path.isdir(x):
  405. X            if askyesno('Recursively remove B directory ' + x, 1):
  406. X                runcmd('rm -rf' + mkarg(x))
  407. X        else:
  408. X            runcmd('rm -f' + mkarg(x))
  409. X        update(w)
  410. X
  411. Xdef cp_ab(w, m, item):
  412. X    x = getselection(w)
  413. X    if x:
  414. X        if x[-1:] = '/': x = x[:-1]
  415. X        ax = path.cat(w.a, x)
  416. X        bx = path.cat(w.b, x)
  417. X        if path.isdir(ax):
  418. X            if path.exists(bx):
  419. X                m = 'Can\'t copy directory to existing target'
  420. X                stdwin.message(m)
  421. X                return
  422. X            runcmd('cp -r' + mkarg(ax) + mkarg(w.b))
  423. X        else:
  424. X            runcmd('cp' + mkarg(ax) + mk2arg(w.b, x))
  425. X        update(w)
  426. X
  427. Xdef cp_ba(w, m, item):
  428. X    x = getselection(w)
  429. X    if x:
  430. X        if x[-1:] = '/': x = x[:-1]
  431. X        ax = path.cat(w.a, x)
  432. X        bx = path.cat(w.b, x)
  433. X        if path.isdir(bx):
  434. X            if path.exists(ax):
  435. X                m = 'Can\'t copy directory to existing target'
  436. X                stdwin.message(m)
  437. X                return
  438. X            runcmd('cp -r' + mkarg(bx) + mkarg(w.a))
  439. X        else:
  440. X            runcmd('cp' + mk2arg(w.b, x) + mkarg(ax))
  441. X        update(w)
  442. X
  443. Xdef nop(args):
  444. X    pass
  445. X
  446. Xdef getselection(w):
  447. X    icol, irow = w.selection
  448. X    if 0 <= icol < len(w.data):
  449. X        if 0 <= irow < len(w.data[icol]):
  450. X            return w.data[icol][irow][0]
  451. X    stdwin.message('no selection')
  452. X    return ''
  453. X
  454. Xdef runcmd(cmd):
  455. X    print cmd
  456. X    sts, output = commands.getstatusoutput(cmd)
  457. X    if sts or output:
  458. X        if not output:
  459. X            output = 'Exit status ' + `sts`
  460. X        stdwin.message(output)
  461. X
  462. X
  463. X# Status menu (for all kinds of windows)
  464. X
  465. Xdef addstatmenu(w, files):
  466. X    w.statmenu = m = w.menucreate('Stat')
  467. X    m.files = files
  468. X    m.action = []
  469. X    for file in files:
  470. X        m.additem(commands.getstatus(file))
  471. X        m.action.append(stataction)
  472. X
  473. Xdef stataction(w, m, item): # Menu item action for stat menu
  474. X    file = m.files[item]
  475. X    try:
  476. X        m.setitem(item, commands.getstatus(file))
  477. X    except posix.error:
  478. X        stdwin.message('Can\'t get status for ' + file)
  479. X
  480. X
  481. X# Compute a suitable window title from two paths
  482. X
  483. Xdef mktitle(a, b):
  484. X    if a = b: return a
  485. X    i = 1
  486. X    while a[-i:] = b[-i:]: i = i+1
  487. X    i = i-1
  488. X    if not i:
  489. X        return a + '  ' + b
  490. X    else:
  491. X        return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:]
  492. X
  493. X
  494. X# Ask a confirmation question
  495. X
  496. Xdef askyesno(prompt, default):
  497. X    try:
  498. X        return stdwin.askync(prompt, default)
  499. X    except KeyboardInterrupt:
  500. X        return 0
  501. X
  502. X
  503. X# Display a message "busy" in a window, and mark it for updating
  504. X
  505. Xdef setbusy(w):
  506. X    left, top = w.getorigin()
  507. X    width, height = w.getwinsize()
  508. X    right, bottom = left + width, top + height
  509. X    d = w.begindrawing()
  510. X    d.erase((0, 0), (10000, 10000))
  511. X    text = 'Busy...'
  512. X    textwidth = d.textwidth(text)
  513. X    textheight = d.lineheight()
  514. X    h, v = left + (width-textwidth)/2, top + (height-textheight)/2
  515. X    d.text((h, v), text)
  516. X    del d
  517. X    w.change((0, 0), (10000, 10000))
  518. X
  519. X
  520. X# Main function
  521. X
  522. Xdef main():
  523. X    print 'wdiff: warning: this version does NOT yet make backups'
  524. X    argv = sys.argv
  525. X    flags = ''
  526. X    if len(argv) >= 2 and argv[1][:1] = '-':
  527. X        flags = argv[1]
  528. X        del argv[1]
  529. X    m = mainmenu() # Create menu earlier than windows
  530. X    if len(argv) = 2: # 1 argument
  531. X        w = anyopen(argv[1])
  532. X        if not w: return
  533. X    elif len(argv) = 3: # 2 arguments
  534. X        w = anydiff(argv[1], argv[2], flags)
  535. X        w.parent = ()
  536. X    else:
  537. X        sys.stdout = sys.stderr
  538. X        print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]'
  539. X        sys.exit(2)
  540. X    del w # It's preserved in gwin.windows
  541. X    while 1:
  542. X        try:
  543. X            gwin.mainloop()
  544. X            break
  545. X        except KeyboardInterrupt:
  546. X            pass    # Just continue...
  547. X
  548. X# Start the main function (this is a script)
  549. Xmain()
  550. EOF
  551. chmod +x 'demo/stdwin/wdiff.py'
  552. fi
  553. if test -s 'lib/Tcl.py'
  554. then echo '*** I will not over-write existing file lib/Tcl.py'
  555. else
  556. echo 'x - lib/Tcl.py'
  557. sed 's/^X//' > 'lib/Tcl.py' << 'EOF'
  558. X# An emulator for John Ousterhout's 'Tcl' language in Python (wow!).
  559. X# Currently only the most basic commands are implemented.
  560. X#
  561. X# Design choices:
  562. X#
  563. X# - Names used for functions are not exactly those used by C Tcl.
  564. X#   In Python, names without 'Tcl_' prefix are acceptable because
  565. X#   names are less global than in C (and often they are prefixed
  566. X#   with a module name anyway).  Parameter conventions also differ.
  567. X#
  568. X# - The Tcl Interpreter type is implemented using a Python class.
  569. X#   Almost all functions with an Interpreter as first parameter are
  570. X#   methods of this class.
  571. X#   Applications can create derived classes to add additional commands
  572. X#   or to override specific internal functions.
  573. X#
  574. X# - Tcl errors are mapped to Python exceptions.
  575. X#   (I bet Ousterhout would have done the same in a language with
  576. X#   a proper exception mechanism).
  577. X#
  578. X# - Tcl expressions are evaluated by Python's built-in function eval().
  579. X#   This makes Python Tcl scripts incompatible with C Tcl scripts,
  580. X#   but is the only sensible solution for a quick-and-dirty version.
  581. X#   It also makes an escape to Python possible.
  582. X#
  583. X# - The Backslash function interprets \<newline>, since it
  584. X#   can return a string instead of a character.
  585. X
  586. X
  587. Xfrom TclUtil import *
  588. X
  589. X
  590. X# Exceptions used to signify 'break' and 'continue'
  591. X
  592. XTclBreak = 'TclBreak'
  593. XTclContinue = 'TclContinue'
  594. XTclReturn = 'TclReturn'
  595. X
  596. X
  597. Xclass CmdBuf():
  598. X    #
  599. X    def Create(buffer):
  600. X        buffer.string = ''
  601. X        return buffer
  602. X    #
  603. X    def Assemble(buffer, str):
  604. X        buffer.string = buffer.string + str
  605. X        if buffer.string[-1:] = '\n':
  606. X            i, end = 0, len(buffer.string)
  607. X            try:
  608. X                while i < end:
  609. X                    list, i = FindNextCommand( \
  610. X                        buffer.string, i, end, 0)
  611. X            except TclMatchingError:
  612. X                return ''
  613. X            except TclSyntaxError:
  614. X                pass # Let Eval() return the error
  615. X            ret = buffer.string
  616. X            buffer.string = ''
  617. X            return ret
  618. X        else:
  619. X            return ''
  620. X
  621. X
  622. Xclass _Frame():
  623. X    def Create(frame):
  624. X        frame.locals = {}
  625. X        return frame
  626. X
  627. Xclass _Proc():
  628. X    #
  629. X    def Create(proc, (interp, args, body)):
  630. X        proc.interp = interp
  631. X        proc.args = SplitList(args)    # Do this once here
  632. X        proc.body = body
  633. X        return proc
  634. X    #
  635. X    def Call(proc, argv):
  636. X        if len(argv) <> len(proc.args)+1:
  637. X            raise TclRuntimeError, \
  638. X                'wrong # args to proc "' + \
  639. X                argv[0] + '"'
  640. X        # XXX No defaults or variable length 'args' yet
  641. X        frame = _Frame().Create()
  642. X        for i in range(len(proc.args)):
  643. X            frame.locals[proc.args[i]] = argv[i+1]
  644. X        proc.interp.stack.append(frame)
  645. X        try:
  646. X            value = proc.interp.Eval(proc.body)
  647. X        except TclReturn, value:
  648. X            pass
  649. X        del proc.interp.stack[-1:]
  650. X        return value
  651. X
  652. X
  653. Ximport regexp
  654. X_expand_prog = regexp.compile('([^[$\\]+|\n)*')
  655. Xdel regexp
  656. X
  657. Xclass Interpreter():
  658. X    #
  659. X    def Create(interp):
  660. X        interp.globals = {}
  661. X        interp.commands = {}
  662. X        interp.stack = []
  663. X        interp.commands['break'] = interp.BreakCmd
  664. X        interp.commands['concat'] = interp.ConcatCmd
  665. X        interp.commands['continue'] = interp.ContinueCmd
  666. X        interp.commands['echo'] = interp.EchoCmd
  667. X        interp.commands['eval'] = interp.EvalCmd
  668. X        interp.commands['expr'] = interp.ExprCmd
  669. X        interp.commands['for'] = interp.ForCmd
  670. X        interp.commands['glob'] = interp.GlobCmd
  671. X        interp.commands['global'] = interp.GlobalCmd
  672. X        interp.commands['if'] = interp.IfCmd
  673. X        interp.commands['index'] = interp.IndexCmd
  674. X        interp.commands['list'] = interp.ListCmd
  675. X        interp.commands['proc'] = interp.ProcCmd
  676. X        interp.commands['rename'] = interp.RenameCmd
  677. X        interp.commands['return'] = interp.ReturnCmd
  678. X        interp.commands['set'] = interp.SetCmd
  679. X        return interp
  680. X    #
  681. X    def Delete(interp):
  682. X        #
  683. X        # Only break circular references here;
  684. X        # most things will be garbage-collected.
  685. X        #
  686. X        for name in interp.commands.keys():
  687. X            del interp.commands[name]
  688. X    #
  689. X    def CreateCommand(interp, (name, proc)):
  690. X        interp.commands[name] = proc
  691. X    #
  692. X    def DeleteCommand(interp, (name)):
  693. X        del interp.commands[name]
  694. X    #
  695. X    # Local variables are maintained on the stack.
  696. X    # A local variable with value "None" is a dummy
  697. X    # meaning that the corresponding global variable
  698. X    # should be used.
  699. X    #
  700. X    def GetVar(interp, varName):
  701. X        dict = interp.globals
  702. X        if interp.stack:
  703. X            d = interp.stack[-1:][0].locals
  704. X            if d.has_key(varName) and d[varName] = None:
  705. X                pass
  706. X            else:
  707. X                dict = d
  708. X        if not dict.has_key(varName):
  709. X            raise TclRuntimeError, \
  710. X                'Variable "' + varName + '" not found'
  711. X        return dict[varName]
  712. X    #
  713. X    def SetVar(interp, (varName, newValue)):
  714. X        dict = interp.globals
  715. X        if interp.stack:
  716. X            d = interp.stack[-1:][0].locals
  717. X            if d.has_key(varName) and d[varName] = None:
  718. X                pass
  719. X            else:
  720. X                dict = d
  721. X        dict[varName] = newValue
  722. X    #
  723. X    def Expand(interp, (str, i, end)):
  724. X        if end <= i: return ''
  725. X        if str[i] = '{' and str[end-1] = '}':
  726. X            return str[i+1:end-1]
  727. X        if str[i] = '"' and str[end-1] = '"':
  728. X            i, end = i+1, end-1
  729. X        result = ''
  730. X        while i < end:
  731. X            c = str[i]
  732. X            if c = '\\':
  733. X                x, i = Backslash(str, i, end)
  734. X                result = result + x
  735. X            elif c = '[':
  736. X                j = BalanceBrackets(str, i, end)
  737. X                x = interp.EvalBasic(str, i+1, j-1, 1)
  738. X                result = result + x
  739. X                i = j
  740. X            elif c = '$':
  741. X                i = i+1
  742. X                j = FindVarName(str, i, end)
  743. X                name = str[i:j]
  744. X                i = j
  745. X                if not name:
  746. X                    result = result + '$'
  747. X                else:
  748. X                    if name[:1] = '{' and name[-1:] = '}':
  749. X                        name = name[1:-1]
  750. X                    result = result + interp.GetVar(name)
  751. X            else:
  752. X                j = _expand_prog.exec(str, i)
  753. X                j = min(j, end)
  754. X                result = result + str[i:j]
  755. X                i = j
  756. X        return result
  757. X    #
  758. X    def EvalBasic(interp, (str, i, end, bracketed)):
  759. X        result = ''
  760. X        while i < end:
  761. X            indexargv, i = FindNextCommand( \
  762. X                    str, i, end, bracketed)
  763. X            if indexargv:
  764. X                argv = []
  765. X                for x, y in indexargv:
  766. X                    arg = interp.Expand(str, x, y)
  767. X                    argv.append(arg)
  768. X                name = argv[0]
  769. X                if not interp.commands.has_key(name):
  770. X                    raise TclRuntimeError, \
  771. X                        'Command "' + name + \
  772. X                        '" not found'
  773. X                result = interp.commands[name](argv)
  774. X        return result
  775. X    #
  776. X    def Eval(interp, str):
  777. X        return interp.EvalBasic(str, 0, len(str), 0)
  778. X    #
  779. X    def ExprBasic(interp, (str, begin, end)):
  780. X        expr = interp.Expand(str, begin, end)
  781. X        i = SkipSpaces(expr, 0, len(expr))
  782. X        expr = expr[i:]
  783. X        try:
  784. X            return eval(expr, {})
  785. X        except (NameError, TypeError, RuntimeError, EOFError), msg:
  786. X            import sys
  787. X            raise TclRuntimeError, sys.exc_type + ': ' + msg
  788. X    #
  789. X    def Expr(interp, str):
  790. X        return interp.ExprBasic(str, 0, len(str))
  791. X    #
  792. X    # The rest are command implementations
  793. X    #
  794. X    def BreakCmd(interp, argv):
  795. X        if len(argv) <> 1:
  796. X            raise TclRuntimeError, 'usage: break'
  797. X        raise TclBreak
  798. X    #
  799. X    def ConcatCmd(interp, argv):
  800. X        if len(argv) < 2:
  801. X            raise TclRuntimeError, 'usage: concat arg ...'
  802. X        return Concat(argv[1:])
  803. X    #
  804. X    def ContinueCmd(interp, argv):
  805. X        if len(argv) <> 1:
  806. X            raise TclRuntimeError, 'usage: continue'
  807. X        raise TclContinue
  808. X    #
  809. X    def EchoCmd(interp, argv):
  810. X        for arg in argv[1:]: print arg,
  811. X        print
  812. X        return ''
  813. X    #
  814. X    def EvalCmd(interp, argv):
  815. X        if len(argv) < 2:
  816. X            raise TclRuntimeError, 'usage: eval arg [arg ...]'
  817. X        str = Concat(argv[1:])
  818. X        return interp.Eval(str)
  819. X    #
  820. X    def ExprCmd(interp, argv):
  821. X        if len(argv) <> 2:
  822. X            raise TclRuntimeError, 'usage: expr expression'
  823. X        expr = argv[1]
  824. X        result = interp.Expr(expr)
  825. X        if type(result) <> type(''): result = `result`
  826. X        return result
  827. X    #
  828. X    def ForCmd(interp, argv):
  829. X        if len(argv) <> 5:
  830. X            raise TclRuntimeError, \
  831. X                'usage: for start test next body'
  832. X        x = interp.Eval(argv[1])
  833. X        while interp.Expr(argv[2]):
  834. X            try:
  835. X                x = interp.Eval(argv[4])
  836. X            except TclBreak:
  837. X                break
  838. X            except TclContinue:
  839. X                pass
  840. X            x = interp.Eval(argv[3])
  841. X        return ''
  842. X    #
  843. X    def GlobCmd(interp, argv):
  844. X        import macglob
  845. X        if len(argv) < 2:
  846. X            raise TclRuntimeError, 'usage: glob pattern ...'
  847. X        list = []
  848. X        for pat in argv[1:]:
  849. X            list = list + macglob.glob(pat)
  850. X        if not list:
  851. X            raise TclRuntimeError, 'no match for glob pattern(s)'
  852. X        return BuildList(list)
  853. X    #
  854. X    def GlobalCmd(interp, argv):
  855. X        if len(argv) < 2:
  856. X            raise TclRuntimeError, 'usage: global varname ...'
  857. X        if not interp.stack:
  858. X            raise TclRuntimeError, 'global used outside proc'
  859. X        dict = interp.stack[-1:][0].locals
  860. X        for name in argv[1:]:
  861. X            dict[name] = None
  862. X        return ''
  863. X    #
  864. X    def IfCmd(interp, argv):
  865. X        argv = argv[:]
  866. X        if len(argv) > 2 and argv[2] = 'then': del argv[2]
  867. X        if len(argv) > 3 and argv[3] = 'else': del argv[3]
  868. X        if not 3 <= len(argv) <= 4:
  869. X            raise TclRuntimeError, \
  870. X             'usage: if test [then] trueBody [else] falseBody'
  871. X        if interp.Expr(argv[1]):
  872. X            return interp.Eval(argv[2])
  873. X        if len(argv) > 3:
  874. X            return interp.Eval(argv[3])
  875. X        return ''
  876. X    #
  877. X    def IndexCmd(interp, argv):
  878. X        if len(argv) <> 3:
  879. X            raise TclRuntimeError, 'usage: index value index'
  880. X        import string
  881. X        try:
  882. X            index = string.atoi(argv[2])
  883. X            if index < 0: raise string.atoi_error
  884. X        except string.atoi_error:
  885. X            raise TclRuntimeError, 'bad index: ' + argv[2]
  886. X        list = SplitList(argv[1])
  887. X        if index >= len(list): return ''
  888. X        return list[index]
  889. X    #
  890. X    def ListCmd(interp, argv):
  891. X        if len(argv) < 2:
  892. X            raise TclRuntimeError, 'usage: list arg ...'
  893. X        return BuildList(argv[1:])
  894. X    #
  895. X    def ProcCmd(interp, argv):
  896. X        if len(argv) <> 4:
  897. X            raise TclRuntimeError, 'usage: proc name args body'
  898. X        x = _Proc().Create(interp, argv[2], argv[3])
  899. X        interp.CreateCommand(argv[1], x.Call)
  900. X        return ''
  901. X    #
  902. X    def RenameCmd(interp, argv):
  903. X        if len(argv) <> 3:
  904. X            raise TclRuntimeError, 'usage: rename oldName newName'
  905. X        oldName, newName = argv[1], argv[2]
  906. X        if not interp.commands.has_key(oldName):
  907. X            raise TclRuntimeError, \
  908. X                'command "' + oldName + '" not found'
  909. X        if newName: interp.commands[newName] = interp.commands[oldName]
  910. X        del interp.commands[oldName]
  911. X        return ''
  912. X    #
  913. X    def ReturnCmd(interp, argv):
  914. X        if not 1 <= len(argv) <= 2:
  915. X            raise TclRuntimeError, 'usage: return [arg]'
  916. X        if len(argv) = 1: raise TclReturn, ''
  917. X        raise TclReturn, argv[1]
  918. X    #
  919. X    def SetCmd(interp, argv):
  920. X        n = len(argv)
  921. X        if not 2 <= n <= 3:
  922. X            raise TclRuntimeError, 'usage: set varname [newvalue]'
  923. X        if n = 2: return interp.GetVar(argv[1])
  924. X        interp.SetVar(argv[1], argv[2])
  925. X        return ''
  926. X
  927. X
  928. X# The rest are just demos:
  929. X
  930. Xdef MainLoop(interp):
  931. X    buffer = CmdBuf().Create()
  932. X    if not interp.globals.has_key('ps1'): interp.globals['ps1'] = '% '
  933. X    if not interp.globals.has_key('ps2'): interp.globals['ps2'] = ''
  934. X    psname = 'ps1'
  935. X    while 1:
  936. X        try:
  937. X            line = raw_input(interp.globals[psname])
  938. X        except (EOFError, KeyboardInterrupt):
  939. X            print
  940. X            break
  941. X        line = buffer.Assemble(line + '\n')
  942. X        if not line:
  943. X            psname = 'ps2'
  944. X        else:
  945. X            psname = 'ps1'
  946. X            try:
  947. X                x = interp.Eval(line)
  948. X                if x <> '': print 'Result:', `x`
  949. X            except (TclRuntimeError, TclSyntaxError, \
  950. X                TclMatchingError), msg:
  951. X                print 'Error:', msg
  952. X            except (TclBreak, TclContinue):
  953. X                print 'Error: break or continue outside loop'
  954. X            except TclReturn, value:
  955. X                # Return outside proc returns to main loop
  956. X                if value: print value
  957. X
  958. X
  959. Xthe_interpreter = Interpreter().Create()
  960. X
  961. Xdef main():
  962. X    MainLoop(the_interpreter)
  963. X
  964. X
  965. X# XXX To do:
  966. X# for proc: "args" and default arguments
  967. X# More commands:
  968. X# case
  969. X# uplevel
  970. X# info
  971. X# string
  972. X# list operations
  973. X# error, catch
  974. X# print
  975. X# scan, format
  976. X# source
  977. X# history?
  978. X# others?
  979. EOF
  980. fi
  981. if test -s 'src/asa.c'
  982. then echo '*** I will not over-write existing file src/asa.c'
  983. else
  984. echo 'x - src/asa.c'
  985. sed 's/^X//' > 'src/asa.c' << 'EOF'
  986. X/***********************************************************
  987. XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  988. XNetherlands.
  989. X
  990. X                        All Rights Reserved
  991. X
  992. XPermission to use, copy, modify, and distribute this software and its 
  993. Xdocumentation for any purpose and without fee is hereby granted, 
  994. Xprovided that the above copyright notice appear in all copies and that
  995. Xboth that copyright notice and this permission notice appear in 
  996. Xsupporting documentation, and that the names of Stichting Mathematisch
  997. XCentrum or CWI not be used in advertising or publicity pertaining to
  998. Xdistribution of the software without specific, written prior permission.
  999. X
  1000. XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1001. XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1002. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  1003. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1004. XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  1005. XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  1006. XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1007. X
  1008. X******************************************************************/
  1009. X
  1010. X/* Asynchronous audio module for Silicon Graphics 4D/20 under IRIX 3.3
  1011. X   Copyright 1990 Stichting Mathematisch Centrum, Amsterdam
  1012. X   Author: Guido van Rossum, <guido@cwi.nl>
  1013. X   Last modified: guido@cwi.nl, Oct 14, 1990
  1014. X
  1015. X   Callers should #include "asa.h".
  1016. X
  1017. X   This code is strongly IRIX 3.3 dependent.  (Or are sproc() and
  1018. X   friends standard SYSV now?)
  1019. X
  1020. X   Caution: if you put printf's in the slave for debugging, use "-lmpc"
  1021. X   to get the semaphore version of stdio!
  1022. X
  1023. X
  1024. X   This file contains two library layers and a test program:
  1025. X
  1026. X
  1027. X   The lower layer implements a simple asynchronous execution facility,
  1028. X   built directly on the system calls sproc() and [un]blockproc().
  1029. X
  1030. X   A slave thread sits in an infinite loop waiting for work assigned to
  1031. X   it by the master thread.  Work is represented by a function pointer
  1032. X   and an argument of type void*.  The function returns a void* pointer
  1033. X   which is transferred back to the master when it submits the next bit
  1034. X   of work.  Submitting a NULL function pointer can be used by the
  1035. X   master to wait for completion of the previous work.  This lower
  1036. X   layer could be generally useful, but is currently implemented by
  1037. X   static functions, for exclusive by the asynchronous audio layer.
  1038. X
  1039. X
  1040. X   The higher layer implements an asynchronous interface to the
  1041. X   /dev/audio device on the Silicon Graphics 4D/20.  It defines the
  1042. X   following functions:
  1043. X   
  1044. X   int asa_init()
  1045. X       Required initialization function.  The other functions will call
  1046. X       abort() when they are called before asa_init().  It creates the
  1047. X    slave process and returns a file descriptor for the audio
  1048. X    device which can be used to set the sampling rate and output
  1049. X    gain, etc.  It prints a message to stderr and returns -1 if the
  1050. X    initialization failed.  Calling this function more than onece is
  1051. X    harmless.
  1052. X   
  1053. X   void asa_start_read(char *buf, int len)
  1054. X       Starts an asynchronous read call on the audio device.  This
  1055. X       waits for completion of the previous request, if any.
  1056. X   
  1057. X   void asa_start_write(char *buf, int len)
  1058. X       Starts an asynchronous write call on the audio device.  This
  1059. X       waits for completion of the previous request, if any.
  1060. X   
  1061. X   int asa_poll()
  1062. X       Polls whether the last asynchronous read or write request is
  1063. X       finished.  Returns -1 if no request was queued, 0 if the request
  1064. X       is not yet finished, and 1 if it is finished.
  1065. X   
  1066. X   int asa_wait()
  1067. X       Waits for completion if the last asynchronous read or write
  1068. X       request.  It returns the result of the read or write request,
  1069. X       and sets the error code to the error code set by the request if
  1070. X       the result is -1.  If no request was queued, this also returns
  1071. X       -1 but leaves the error code unchanged.  Note: to get the error
  1072. X       code, don't inspect the global variable errno but call the
  1073. X       function oserror().
  1074. X   
  1075. X   int asa_cancel()
  1076. X       Cancels the last asynchronous read or write request (by sending
  1077. X       the slave thread a signal for which it has a handler) then
  1078. X       returns its result and error code as asa_wait().
  1079. X   
  1080. X   void asa_done()
  1081. X       Kills the slave process and closes the audio device.  After
  1082. X       this, if further use of the module is required, asa_init()
  1083. X       should be called again.  Calling this function when asa_init()
  1084. X       has not been called is harmless.
  1085. X
  1086. X
  1087. X   Finally, this file contains a simple test program that is compiled if
  1088. X   MAIN is defined (e.g., compile with cc -DMAIN).  It makes a recording
  1089. X   and plays it back.  The user must indicate begin and end of recording
  1090. X   and play-back by pressing the Return key.
  1091. X*/
  1092. X
  1093. X
  1094. X#include <stdio.h>
  1095. X#include <stdlib.h>
  1096. X#include <signal.h>
  1097. X#include <sys/types.h>
  1098. X#include <sys/prctl.h>
  1099. X
  1100. X#include "asa.h"
  1101. X
  1102. X
  1103. X/* Asynchronous execution facility (lower layer) */
  1104. X
  1105. X
  1106. X/* Signal used to cancel requests in progress */
  1107. X#define MYSIG SIGUSR1
  1108. X
  1109. X/* Respective process IDs */
  1110. Xstatic pid_t master_pid = -1;
  1111. Xstatic pid_t slave_pid = -1;
  1112. X
  1113. X/* Work and result "queue" (1 element) */
  1114. Xstatic void * (*work_func)();
  1115. Xstatic void *work_arg;
  1116. Xstatic void *work_result;
  1117. X
  1118. X/* Signal handler for MYSIG -- interrupts read or write system call */
  1119. X
  1120. X/*ARGSUSED*/
  1121. Xstatic void
  1122. Xhandler(sig)
  1123. X    int sig;
  1124. X{
  1125. X    /* Reinstate the handler (non-BSD signal semantics) */
  1126. X    signal(sig, handler);
  1127. X}
  1128. X
  1129. X/* Subroutine to fiddle signals */
  1130. X
  1131. Xstatic void
  1132. Xdosig(sig)
  1133. X    int sig;
  1134. X{
  1135. X    if (signal(sig, SIG_IGN) != SIG_IGN)
  1136. X        signal(sig, SIG_DFL);
  1137. X}
  1138. X
  1139. X/* Slave control flow */
  1140. X
  1141. X/*ARGSUSED*/
  1142. Xstatic void
  1143. Xslave(arg)
  1144. X    void *arg;
  1145. X{
  1146. X    void * (*func)();
  1147. X    void *arg;
  1148. X    void *result;
  1149. X    
  1150. X    /* Reset signal handlers that interactive programs often catch.
  1151. X       The assumption is that if the master has a handler for these
  1152. X       signals, it will be a cleanup function.  The slave must die
  1153. X       from these. */
  1154. X    dosig(SIGHUP);
  1155. X    dosig(SIGQUIT);
  1156. X    dosig(SIGTERM);
  1157. X    dosig(SIGPIPE);
  1158. X    
  1159. X    /* Ignore SIGINT if caught or ignored */
  1160. X    if (signal(SIGINT, SIG_IGN) == SIG_DFL)
  1161. X        signal(SIGINT, SIG_DFL);
  1162. X    
  1163. X    /* Let the handler install itself */
  1164. X    handler(MYSIG);
  1165. X    
  1166. X    /* Set slave_pid.  This is also done in the master thread, but
  1167. X       there is a race condition whereby the slave begins execution
  1168. X       before the master has assigned the result of sproc() to
  1169. X       slave_pid.  So we set it here as well -- since this sets the
  1170. X       same value it should be OK. */
  1171. X    slave_pid = getpid();
  1172. X    
  1173. X    /* Set the dummy result returned by the first rendezvous */
  1174. X    result = NULL;
  1175. X    
  1176. X    /* Loop forever, waiting for and executing work */
  1177. X    for (;;) {
  1178. X        /* First rendezvous: store previous result */
  1179. X        if (blockproc(slave_pid) < 0)
  1180. X            perror("slave: [result] blockproc(slave_pid)");
  1181. X        work_result = result;
  1182. X        if (unblockproc(master_pid) < 0)
  1183. X            perror("slave: [result] unblockproc(master_pid)");
  1184. X        
  1185. X        /* Second rendezvous: fetch work */
  1186. X        if (blockproc(slave_pid) < 0)
  1187. X            perror("slave: [func,arg] blockproc(slave_pid)");
  1188. X        func = work_func;
  1189. X        arg = work_arg;
  1190. X        if (unblockproc(master_pid) < 0)
  1191. X            perror("slave: [func,arg] unblockproc(master_pid)");
  1192. X        
  1193. X        /* Execute work, computing new result */
  1194. X        if (func == NULL) {
  1195. X            result = arg;
  1196. X        }
  1197. X        else {
  1198. X            result = (*func)(arg);
  1199. X        }
  1200. X    }
  1201. X}
  1202. X
  1203. Xstatic int
  1204. Xslave_init()
  1205. X{
  1206. X    if (slave_pid > 0)
  1207. X        return slave_pid;
  1208. X    master_pid = getpid();
  1209. X    
  1210. X    /* Reset the queue, in case this is a re-init after asa_done() */
  1211. X    work_result = NULL;
  1212. X    work_func = NULL;
  1213. X    work_arg = NULL;
  1214. X    
  1215. X    /* Create the slave process, sharing all segments and properties */
  1216. X    slave_pid = sproc(slave, PR_SALL, (char *)NULL);
  1217. X    if (slave_pid < 0)
  1218. X        perror("slave_init: sproc(slave, PR_SALL, NULL)");
  1219. X    
  1220. X    /* Set up initial conditions---tricky!
  1221. X       Both the master and the slave start with one credit, since
  1222. X       both the result slot and the work/func slots are initially
  1223. X       free.
  1224. X       Note that we use setblockproccnt() for the master so a
  1225. X       possible indeterminate semaphore value caused by a previous
  1226. X       asa_done() at an unfortunate moment doesn't harm us.
  1227. X    */
  1228. X    setblockproccnt(master_pid, 1);
  1229. X    unblockproc(slave_pid);
  1230. X    
  1231. X    return slave_pid;
  1232. X}
  1233. X
  1234. Xstatic void
  1235. Xslave_done()
  1236. X{
  1237. X    if (slave_pid > 0) {
  1238. X        if (kill(slave_pid, SIGKILL) < 0)
  1239. X            perror("slave_done: kill(slave_pid, SIGKILL)");
  1240. X    }
  1241. X    slave_pid = -1;
  1242. X}
  1243. X
  1244. X/* Queue new work and return result of previous work */
  1245. X
  1246. Xstatic void *
  1247. Xrendezvous(func, arg)
  1248. X    void * (*func)();
  1249. X    void *arg;
  1250. X{
  1251. X    void *result;
  1252. X    
  1253. X    if (slave_pid <= 0)
  1254. X        abort(); /* Illegal call: not initialized properly */
  1255. X    
  1256. X    /* First rendezvous: store new work */
  1257. X    if (blockproc(master_pid) < 0)
  1258. X        perror("rendezvous: [func,arg] blockproc(master_pid)");
  1259. X    work_func = func;
  1260. X    work_arg = arg;
  1261. X    if (unblockproc(slave_pid) < 0)
  1262. X        perror("rendezvous: [func,arg] unblockproc(slave_pid)");
  1263. X    
  1264. X    /* Second rendezvous: fetch previous result */
  1265. X    if (blockproc(master_pid) < 0)
  1266. X        perror("rendezvous: [result] blockproc(master_pid)");
  1267. X    result = work_result;
  1268. X    if (unblockproc(slave_pid) < 0)
  1269. X        perror("rendezvous: [result] unblockproc(slave_pid)");
  1270. X    
  1271. X    return result;
  1272. X}
  1273. X
  1274. X
  1275. X/* Asynchronous audio interface (higher layer) */
  1276. X
  1277. X
  1278. Xint audio_fd = -1;    /* File descriptor -- not initialized yet */
  1279. X
  1280. Xstatic struct queue {
  1281. X    int func;    /* 0 = read, 1 = write */
  1282. X    char *buf;
  1283. X    int len;
  1284. X    int result;
  1285. X    int error;
  1286. X} queue[2];
  1287. X
  1288. Xstatic int qindex = 0;
  1289. X
  1290. Xint
  1291. Xasa_init()
  1292. X{
  1293. X    int fd;
  1294. X    char *p;
  1295. X    
  1296. X    if (audio_fd >= 0)
  1297. X        return audio_fd;
  1298. X    fd = open("/dev/audio", 2);
  1299. X    if (fd < 0) {
  1300. X        perror("asa_init: Can't open /dev/audio");
  1301. X        return -1;
  1302. X    }
  1303. X    if (slave_init() < 0) {
  1304. X        perror("asa_init: Can't create slave process");
  1305. X        close(fd);
  1306. X        return -1;
  1307. X    }
  1308. X    audio_fd = fd;
  1309. X    return fd;
  1310. X}
  1311. X
  1312. Xvoid
  1313. Xasa_done()
  1314. X{
  1315. X    slave_done();
  1316. X    if (audio_fd >= 0) {
  1317. X        if (close(audio_fd) < 0)
  1318. X            perror("asa_done: close(audio_fd)");
  1319. X    }
  1320. X    audio_fd = -1;
  1321. X}
  1322. X
  1323. Xstatic void *
  1324. Xrunjob(arg)
  1325. X    void *arg;
  1326. X{
  1327. X    extern int errno;
  1328. X    struct queue *q = (struct queue *)arg;
  1329. X    char *buf = q->buf;
  1330. X    int len = q->len;
  1331. X    int n = 0;
  1332. X    
  1333. X    if (q->func == 0)
  1334. X        n = read(audio_fd, buf, len);
  1335. X    else
  1336. X        n = write(audio_fd, buf, len);
  1337. X    if (q->func == 0 && n >= 0) {
  1338. X        while (--len >= n && buf[len] == '\0')
  1339. X            ;
  1340. X        n = len+1;
  1341. X    }
  1342. X    q->result = n;
  1343. X    q->error = oserror();
  1344. X    return arg;
  1345. X}
  1346. X
  1347. Xstatic void
  1348. Xstartjob(func, buf, len)
  1349. X    int func;
  1350. X    char *buf;
  1351. X    int len;
  1352. X{
  1353. X    struct queue *q;
  1354. X    
  1355. X    q = &queue[qindex];
  1356. X    qindex = (qindex+1) & 1;
  1357. X    q->func = func;
  1358. X    q->buf = buf;
  1359. X    q->len = len;
  1360. X    (void) rendezvous(runjob, (void *)q);
  1361. X}
  1362. X
  1363. Xvoid
  1364. Xasa_start_read(buf, len)
  1365. X    char *buf;
  1366. X    int len;
  1367. X{
  1368. X    memset(buf, '\0', len);
  1369. X    startjob(0, buf, len);
  1370. X}
  1371. X
  1372. Xvoid
  1373. Xasa_start_write(buf, len)
  1374. X    char *buf;
  1375. X    int len;
  1376. X{
  1377. X    startjob(1, buf, len);
  1378. X}
  1379. X
  1380. Xint
  1381. Xasa_wait()
  1382. X{
  1383. X    struct queue *q;
  1384. X    
  1385. X    q = (struct queue *) rendezvous((void*(*)())NULL, (void *)NULL);
  1386. X    if (q == NULL) {
  1387. X        setoserror(0);
  1388. X        return -1; /* No work was queued */
  1389. X    }
  1390. X    setoserror(q->error);
  1391. X    return q->result;
  1392. X}
  1393. X
  1394. Xint
  1395. Xasa_poll()
  1396. X{
  1397. X    int err;
  1398. X    
  1399. X    err = prctl(PR_ISBLOCKED, slave_pid);
  1400. X    if (err < 0) {
  1401. X        perror("prctl(PR_ISBLOCKED, slave_pid)");
  1402. X        return -1;
  1403. X    }
  1404. X    else if (err == 0)
  1405. X        return 0;
  1406. X    else if (work_result == NULL) {
  1407. X        setoserror(0);
  1408. X        return -1;
  1409. X    }
  1410. X    else
  1411. X        return 1;
  1412. X}
  1413. X
  1414. Xint
  1415. Xasa_cancel()
  1416. X{
  1417. X    int result;
  1418. X    
  1419. X    kill(slave_pid, MYSIG);
  1420. X    result = asa_wait();
  1421. X    return result;
  1422. X}
  1423. X
  1424. X
  1425. X#ifdef MAIN
  1426. X
  1427. X/* Test program */
  1428. X
  1429. X#include <sys/audio.h>
  1430. X
  1431. Xmain()
  1432. X{
  1433. X    static char buf[10*16*1024]; /* 10 seconds of sound at 16K/sec */
  1434. X    int n;
  1435. X    int afd;
  1436. X    
  1437. X    if ((afd = asa_init()) < 0)
  1438. X        exit(1);
  1439. X    ioctl(afd, AUDIOCSETRATE, 3);
  1440. X    ioctl(afd, AUDIOCSETOUTGAIN, 0);
  1441. X    printf("Poll returns %d\n", asa_poll());
  1442. X    go("Hit enter to start recording:\n");
  1443. X    asa_start_read(buf, sizeof buf);
  1444. X    go("Hit enter to stop recording:\n");
  1445. X    /*printf("Poll returns %d\n", asa_poll());*/
  1446. X    n = asa_cancel();
  1447. X    if (n < 0)
  1448. X        perror("Read failed");
  1449. X    else {
  1450. X        printf("Got %d bytes\n", n);
  1451. X        printf("Poll returns %d\n", asa_poll());
  1452. X        go("Hit enter to start playing:\n");
  1453. X        ioctl(afd, AUDIOCSETOUTGAIN, 50);
  1454. X        asa_start_write(buf, n);
  1455. X        go("Hit enter to stop playing:\n");
  1456. X        printf("Poll returns %d\n", asa_poll());
  1457. X        n = asa_cancel();
  1458. X        if (n < 0)
  1459. X            perror("Write failed");
  1460. X        else
  1461. X            printf("Stopped at %d bytes\n", n);
  1462. X    }
  1463. X    ioctl(afd, AUDIOCSETOUTGAIN, 0);
  1464. X    asa_done();
  1465. X    exit(n < 0 ? 1 : 0);
  1466. X}
  1467. X
  1468. Xgo(str)
  1469. X    char *str;
  1470. X{
  1471. X    char line[100];
  1472. X    
  1473. X    sleep(1);
  1474. X    fputs(str, stdout);
  1475. X    fflush(stdout);
  1476. X    fgets(line, sizeof line, stdin);
  1477. X}
  1478. X
  1479. X#endif /* MAIN */
  1480. EOF
  1481. fi
  1482. if test -s 'src/bltinmodule.c'
  1483. then echo '*** I will not over-write existing file src/bltinmodule.c'
  1484. else
  1485. echo 'x - src/bltinmodule.c'
  1486. sed 's/^X//' > 'src/bltinmodule.c' << 'EOF'
  1487. X/***********************************************************
  1488. XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  1489. XNetherlands.
  1490. X
  1491. X                        All Rights Reserved
  1492. X
  1493. XPermission to use, copy, modify, and distribute this software and its 
  1494. Xdocumentation for any purpose and without fee is hereby granted, 
  1495. Xprovided that the above copyright notice appear in all copies and that
  1496. Xboth that copyright notice and this permission notice appear in 
  1497. Xsupporting documentation, and that the names of Stichting Mathematisch
  1498. XCentrum or CWI not be used in advertising or publicity pertaining to
  1499. Xdistribution of the software without specific, written prior permission.
  1500. X
  1501. XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1502. XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1503. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  1504. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1505. XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  1506. XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  1507. XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1508. X
  1509. X******************************************************************/
  1510. X
  1511. X/* Built-in functions */
  1512. X
  1513. X#include "allobjects.h"
  1514. X
  1515. X#include "node.h"
  1516. X#include "graminit.h"
  1517. X#include "errcode.h"
  1518. X#include "sysmodule.h"
  1519. X#include "bltinmodule.h"
  1520. X#include "import.h"
  1521. X#include "pythonrun.h"
  1522. X#include "compile.h" /* For ceval.h */
  1523. X#include "ceval.h"
  1524. X#include "modsupport.h"
  1525. X
  1526. Xstatic object *
  1527. Xbuiltin_abs(self, v)
  1528. X    object *self;
  1529. X    object *v;
  1530. X{
  1531. X    /* XXX This should be a method in the as_number struct in the type */
  1532. X    if (v == NULL) {
  1533. X        /* */
  1534. X    }
  1535. X    else if (is_intobject(v)) {
  1536. X        long x = getintvalue(v);
  1537. X        if (x < 0)
  1538. X            x = -x;
  1539. X        return newintobject(x);
  1540. X    }
  1541. X    else if (is_floatobject(v)) {
  1542. X        double x = getfloatvalue(v);
  1543. X        if (x < 0)
  1544. X            x = -x;
  1545. X        return newfloatobject(x);
  1546. X    }
  1547. X    err_setstr(TypeError, "abs() argument must be float or int");
  1548. X    return NULL;
  1549. X}
  1550. X
  1551. Xstatic object *
  1552. Xbuiltin_chr(self, v)
  1553. X    object *self;
  1554. X    object *v;
  1555. X{
  1556. X    long x;
  1557. X    char s[1];
  1558. X    if (v == NULL || !is_intobject(v)) {
  1559. X        err_setstr(TypeError, "chr() must have int argument");
  1560. X        return NULL;
  1561. X    }
  1562. X    x = getintvalue(v);
  1563. X    if (x < 0 || x >= 256) {
  1564. X        err_setstr(RuntimeError, "chr() arg not in range(256)");
  1565. X        return NULL;
  1566. X    }
  1567. X    s[0] = x;
  1568. X    return newsizedstringobject(s, 1);
  1569. X}
  1570. X
  1571. Xstatic object *
  1572. Xbuiltin_dir(self, v)
  1573. X    object *self;
  1574. X    object *v;
  1575. X{
  1576. X    object *d;
  1577. X    if (v == NULL) {
  1578. X        d = getlocals();
  1579. X    }
  1580. X    else {
  1581. X        if (!is_moduleobject(v)) {
  1582. X            err_setstr(TypeError,
  1583. X                "dir() argument, must be module or absent");
  1584. X            return NULL;
  1585. X        }
  1586. X        d = getmoduledict(v);
  1587. X    }
  1588. X    v = getdictkeys(d);
  1589. X    if (sortlist(v) != 0) {
  1590. X        DECREF(v);
  1591. X        v = NULL;
  1592. X    }
  1593. X    return v;
  1594. X}
  1595. X
  1596. Xstatic object *
  1597. Xbuiltin_divmod(self, v)
  1598. X    object *self;
  1599. X    object *v;
  1600. X{
  1601. X    object *x, *y;
  1602. X    long xi, yi, xdivy, xmody;
  1603. X    if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
  1604. X        err_setstr(TypeError, "divmod() requires 2 int arguments");
  1605. X        return NULL;
  1606. X    }
  1607. X    x = gettupleitem(v, 0);
  1608. X    y = gettupleitem(v, 1);
  1609. X    if (!is_intobject(x) || !is_intobject(y)) {
  1610. X        err_setstr(TypeError, "divmod() requires 2 int arguments");
  1611. X        return NULL;
  1612. X    }
  1613. X    xi = getintvalue(x);
  1614. X    yi = getintvalue(y);
  1615. X    if (yi == 0) {
  1616. X        err_setstr(TypeError, "divmod() division by zero");
  1617. X        return NULL;
  1618. X    }
  1619. X    if (yi < 0) {
  1620. X        xdivy = -xi / -yi;
  1621. X    }
  1622. X    else {
  1623. X        xdivy = xi / yi;
  1624. X    }
  1625. X    xmody = xi - xdivy*yi;
  1626. X    if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
  1627. X        xmody += yi;
  1628. X        xdivy -= 1;
  1629. X    }
  1630. X    v = newtupleobject(2);
  1631. X    x = newintobject(xdivy);
  1632. X    y = newintobject(xmody);
  1633. X    if (v == NULL || x == NULL || y == NULL ||
  1634. X        settupleitem(v, 0, x) != 0 ||
  1635. X        settupleitem(v, 1, y) != 0) {
  1636. X        XDECREF(v);
  1637. X        XDECREF(x);
  1638. X        XDECREF(y);
  1639. X        return NULL;
  1640. X    }
  1641. X    return v;
  1642. X}
  1643. X
  1644. Xstatic object *
  1645. Xexec_eval(v, start)
  1646. X    object *v;
  1647. X    int start;
  1648. X{
  1649. X    object *str = NULL, *globals = NULL, *locals = NULL;
  1650. X    int n;
  1651. X    if (v != NULL) {
  1652. X        if (is_stringobject(v))
  1653. X            str = v;
  1654. X        else if (is_tupleobject(v) &&
  1655. X                ((n = gettuplesize(v)) == 2 || n == 3)) {
  1656. X            str = gettupleitem(v, 0);
  1657. X            globals = gettupleitem(v, 1);
  1658. X            if (n == 3)
  1659. X                locals = gettupleitem(v, 2);
  1660. X        }
  1661. X    }
  1662. X    if (str == NULL || !is_stringobject(str) ||
  1663. X            globals != NULL && !is_dictobject(globals) ||
  1664. X            locals != NULL && !is_dictobject(locals)) {
  1665. X        err_setstr(TypeError,
  1666. X            "exec/eval arguments must be string[,dict[,dict]]");
  1667. X        return NULL;
  1668. X    }
  1669. X    return run_string(getstringvalue(str), start, globals, locals);
  1670. X}
  1671. X
  1672. Xstatic object *
  1673. Xbuiltin_eval(self, v)
  1674. X    object *self;
  1675. X    object *v;
  1676. X{
  1677. X    return exec_eval(v, eval_input);
  1678. X}
  1679. X
  1680. Xstatic object *
  1681. Xbuiltin_exec(self, v)
  1682. X    object *self;
  1683. X    object *v;
  1684. X{
  1685. X    return exec_eval(v, file_input);
  1686. X}
  1687. X
  1688. Xstatic object *
  1689. Xbuiltin_float(self, v)
  1690. X    object *self;
  1691. X    object *v;
  1692. X{
  1693. X    if (v == NULL) {
  1694. X        /* */
  1695. X    }
  1696. X    else if (is_floatobject(v)) {
  1697. X        INCREF(v);
  1698. X        return v;
  1699. X    }
  1700. X    else if (is_intobject(v)) {
  1701. X        long x = getintvalue(v);
  1702. X        return newfloatobject((double)x);
  1703. X    }
  1704. X    err_setstr(TypeError, "float() argument must be float or int");
  1705. X    return NULL;
  1706. X}
  1707. X
  1708. Xstatic object *
  1709. Xbuiltin_input(self, v)
  1710. X    object *self;
  1711. X    object *v;
  1712. X{
  1713. X    FILE *in = sysgetfile("stdin", stdin);
  1714. X    FILE *out = sysgetfile("stdout", stdout);
  1715. X    node *n;
  1716. X    int err;
  1717. X    object *m, *d;
  1718. X    flushline();
  1719. X    if (v != NULL)
  1720. X        printobject(v, out, PRINT_RAW);
  1721. X    m = add_module("__main__");
  1722. X    d = getmoduledict(m);
  1723. X    return run_file(in, "<stdin>", expr_input, d, d);
  1724. X}
  1725. X
  1726. Xstatic object *
  1727. Xbuiltin_int(self, v)
  1728. X    object *self;
  1729. X    object *v;
  1730. X{
  1731. X    if (v == NULL) {
  1732. X        /* */
  1733. X    }
  1734. X    else if (is_intobject(v)) {
  1735. X        INCREF(v);
  1736. X        return v;
  1737. X    }
  1738. X    else if (is_floatobject(v)) {
  1739. X        double x = getfloatvalue(v);
  1740. X        return newintobject((long)x);
  1741. X    }
  1742. X    err_setstr(TypeError, "int() argument must be float or int");
  1743. X    return NULL;
  1744. X}
  1745. X
  1746. Xstatic object *
  1747. Xbuiltin_len(self, v)
  1748. X    object *self;
  1749. X    object *v;
  1750. X{
  1751. X    long len;
  1752. X    typeobject *tp;
  1753. X    if (v == NULL) {
  1754. X        err_setstr(TypeError, "len() without argument");
  1755. X        return NULL;
  1756. X    }
  1757. X    tp = v->ob_type;
  1758. X    if (tp->tp_as_sequence != NULL) {
  1759. X        len = (*tp->tp_as_sequence->sq_length)(v);
  1760. X    }
  1761. X    else if (tp->tp_as_mapping != NULL) {
  1762. X        len = (*tp->tp_as_mapping->mp_length)(v);
  1763. X    }
  1764. X    else {
  1765. X        err_setstr(TypeError, "len() of unsized object");
  1766. X        return NULL;
  1767. X    }
  1768. X    return newintobject(len);
  1769. X}
  1770. X
  1771. Xstatic object *
  1772. Xmin_max(v, sign)
  1773. X    object *v;
  1774. X    int sign;
  1775. X{
  1776. X    int i, n, cmp;
  1777. X    object *w, *x;
  1778. X    sequence_methods *sq;
  1779. X    if (v == NULL) {
  1780. X        err_setstr(TypeError, "min() or max() without argument");
  1781. X        return NULL;
  1782. X    }
  1783. X    sq = v->ob_type->tp_as_sequence;
  1784. X    if (sq == NULL) {
  1785. X        err_setstr(TypeError, "min() or max() of non-sequence");
  1786. X        return NULL;
  1787. X    }
  1788. X    n = (*sq->sq_length)(v);
  1789. X    if (n == 0) {
  1790. X        err_setstr(RuntimeError, "min() or max() of empty sequence");
  1791. X        return NULL;
  1792. X    }
  1793. X    w = (*sq->sq_item)(v, 0); /* Implies INCREF */
  1794. X    for (i = 1; i < n; i++) {
  1795. X        x = (*sq->sq_item)(v, i); /* Implies INCREF */
  1796. X        cmp = cmpobject(x, w);
  1797. X        if (cmp * sign > 0) {
  1798. X            DECREF(w);
  1799. X            w = x;
  1800. X        }
  1801. X        else
  1802. X            DECREF(x);
  1803. X    }
  1804. X    return w;
  1805. X}
  1806. X
  1807. Xstatic object *
  1808. Xbuiltin_min(self, v)
  1809. X    object *self;
  1810. X    object *v;
  1811. X{
  1812. X    return min_max(v, -1);
  1813. X}
  1814. X
  1815. Xstatic object *
  1816. Xbuiltin_max(self, v)
  1817. X    object *self;
  1818. X    object *v;
  1819. X{
  1820. X    return min_max(v, 1);
  1821. X}
  1822. X
  1823. Xstatic object *
  1824. Xbuiltin_open(self, v)
  1825. X    object *self;
  1826. X    object *v;
  1827. X{
  1828. X    object *name, *mode;
  1829. X    if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2 ||
  1830. X        !is_stringobject(name = gettupleitem(v, 0)) ||
  1831. X        !is_stringobject(mode = gettupleitem(v, 1))) {
  1832. X        err_setstr(TypeError, "open() requires 2 string arguments");
  1833. X        return NULL;
  1834. X    }
  1835. X    v = newfileobject(getstringvalue(name), getstringvalue(mode));
  1836. X    return v;
  1837. X}
  1838. X
  1839. Xstatic object *
  1840. Xbuiltin_ord(self, v)
  1841. X    object *self;
  1842. X    object *v;
  1843. X{
  1844. X    if (v == NULL || !is_stringobject(v)) {
  1845. X        err_setstr(TypeError, "ord() must have string argument");
  1846. X        return NULL;
  1847. X    }
  1848. X    if (getstringsize(v) != 1) {
  1849. X        err_setstr(RuntimeError, "ord() arg must have length 1");
  1850. X        return NULL;
  1851. X    }
  1852. X    return newintobject((long)(getstringvalue(v)[0] & 0xff));
  1853. X}
  1854. X
  1855. Xstatic object *
  1856. Xbuiltin_range(self, v)
  1857. X    object *self;
  1858. X    object *v;
  1859. X{
  1860. X    static char *errmsg = "range() requires 1-3 int arguments";
  1861. X    int i, n;
  1862. X    long ilow, ihigh, istep;
  1863. X    if (v != NULL && is_intobject(v)) {
  1864. X        ilow = 0; ihigh = getintvalue(v); istep = 1;
  1865. X    }
  1866. X    else if (v == NULL || !is_tupleobject(v)) {
  1867. X        err_setstr(TypeError, errmsg);
  1868. X        return NULL;
  1869. X    }
  1870. X    else {
  1871. X        n = gettuplesize(v);
  1872. X        if (n < 1 || n > 3) {
  1873. X            err_setstr(TypeError, errmsg);
  1874. X            return NULL;
  1875. X        }
  1876. X        for (i = 0; i < n; i++) {
  1877. X            if (!is_intobject(gettupleitem(v, i))) {
  1878. X                err_setstr(TypeError, errmsg);
  1879. X                return NULL;
  1880. X            }
  1881. X        }
  1882. X        if (n == 3) {
  1883. X            istep = getintvalue(gettupleitem(v, 2));
  1884. X            --n;
  1885. X        }
  1886. X        else
  1887. X            istep = 1;
  1888. X        ihigh = getintvalue(gettupleitem(v, --n));
  1889. X        if (n > 0)
  1890. X            ilow = getintvalue(gettupleitem(v, 0));
  1891. X        else
  1892. X            ilow = 0;
  1893. X    }
  1894. X    if (istep == 0) {
  1895. X        err_setstr(RuntimeError, "zero step for range()");
  1896. X        return NULL;
  1897. X    }
  1898. X    /* XXX ought to check overflow of subtraction */
  1899. X    if (istep > 0)
  1900. X        n = (ihigh - ilow + istep - 1) / istep;
  1901. X    else
  1902. X        n = (ihigh - ilow + istep + 1) / istep;
  1903. X    if (n < 0)
  1904. X        n = 0;
  1905. X    v = newlistobject(n);
  1906. X    if (v == NULL)
  1907. X        return NULL;
  1908. X    for (i = 0; i < n; i++) {
  1909. X        object *w = newintobject(ilow);
  1910. X        if (w == NULL) {
  1911. X            DECREF(v);
  1912. X            return NULL;
  1913. X        }
  1914. X        setlistitem(v, i, w);
  1915. X        ilow += istep;
  1916. X    }
  1917. X    return v;
  1918. X}
  1919. X
  1920. Xstatic object *
  1921. Xbuiltin_raw_input(self, v)
  1922. X    object *self;
  1923. X    object *v;
  1924. X{
  1925. X    FILE *in = sysgetfile("stdin", stdin);
  1926. X    FILE *out = sysgetfile("stdout", stdout);
  1927. X    char *p;
  1928. X    int err;
  1929. X    int n = 1000;
  1930. X    flushline();
  1931. X    if (v != NULL)
  1932. X        printobject(v, out, PRINT_RAW);
  1933. X    v = newsizedstringobject((char *)NULL, n);
  1934. X    if (v != NULL) {
  1935. X        if ((err = fgets_intr(getstringvalue(v), n+1, in)) != E_OK) {
  1936. X            err_input(err);
  1937. X            DECREF(v);
  1938. X            return NULL;
  1939. X        }
  1940. X        else {
  1941. X            n = strlen(getstringvalue(v));
  1942. X            if (n > 0 && getstringvalue(v)[n-1] == '\n')
  1943. X                n--;
  1944. X            resizestring(&v, n);
  1945. X        }
  1946. X    }
  1947. X    return v;
  1948. X}
  1949. X
  1950. Xstatic object *
  1951. Xbuiltin_reload(self, v)
  1952. X    object *self;
  1953. X    object *v;
  1954. X{
  1955. X    return reload_module(v);
  1956. X}
  1957. X
  1958. Xstatic object *
  1959. Xbuiltin_type(self, v)
  1960. X    object *self;
  1961. X    object *v;
  1962. X{
  1963. X    if (v == NULL) {
  1964. X        err_setstr(TypeError, "type() requres an argument");
  1965. X        return NULL;
  1966. X    }
  1967. X    v = (object *)v->ob_type;
  1968. X    INCREF(v);
  1969. X    return v;
  1970. X}
  1971. X
  1972. Xstatic struct methodlist builtin_methods[] = {
  1973. X    {"abs", builtin_abs},
  1974. X    {"chr", builtin_chr},
  1975. X    {"dir", builtin_dir},
  1976. X    {"divmod", builtin_divmod},
  1977. X    {"eval", builtin_eval},
  1978. X    {"exec", builtin_exec},
  1979. X    {"float", builtin_float},
  1980. X    {"input", builtin_input},
  1981. X    {"int", builtin_int},
  1982. X    {"len", builtin_len},
  1983. X    {"max", builtin_max},
  1984. X    {"min", builtin_min},
  1985. X    {"open", builtin_open}, /* XXX move to OS module */
  1986. X    {"ord", builtin_ord},
  1987. X    {"range", builtin_range},
  1988. X    {"raw_input", builtin_raw_input},
  1989. X    {"reload", builtin_reload},
  1990. X    {"type", builtin_type},
  1991. X    {NULL, NULL},
  1992. X};
  1993. X
  1994. Xstatic object *builtin_dict;
  1995. X
  1996. Xobject *
  1997. Xgetbuiltin(name)
  1998. X    char *name;
  1999. X{
  2000. X    return dictlookup(builtin_dict, name);
  2001. X}
  2002. X
  2003. X/* Predefined exceptions */
  2004. X
  2005. Xobject *RuntimeError;
  2006. Xobject *EOFError;
  2007. Xobject *TypeError;
  2008. Xobject *MemoryError;
  2009. Xobject *NameError;
  2010. Xobject *SystemError;
  2011. Xobject *KeyboardInterrupt;
  2012. X
  2013. Xstatic object *
  2014. Xnewstdexception(name, message)
  2015. X    char *name, *message;
  2016. X{
  2017. X    object *v = newstringobject(message);
  2018. X    if (v == NULL || dictinsert(builtin_dict, name, v) != 0)
  2019. X        fatal("no mem for new standard exception");
  2020. X    return v;
  2021. X}
  2022. X
  2023. Xstatic void
  2024. Xiniterrors()
  2025. X{
  2026. X    RuntimeError = newstdexception("RuntimeError", "run-time error");
  2027. X    EOFError = newstdexception("EOFError", "end-of-file read");
  2028. X    TypeError = newstdexception("TypeError", "type error");
  2029. X    MemoryError = newstdexception("MemoryError", "out of memory");
  2030. X    NameError = newstdexception("NameError", "undefined name");
  2031. X    SystemError = newstdexception("SystemError", "system error");
  2032. X    KeyboardInterrupt =
  2033. X        newstdexception("KeyboardInterrupt", "keyboard interrupt");
  2034. X}
  2035. X
  2036. Xvoid
  2037. Xinitbuiltin()
  2038. X{
  2039. X    object *m;
  2040. X    m = initmodule("builtin", builtin_methods);
  2041. X    builtin_dict = getmoduledict(m);
  2042. X    INCREF(builtin_dict);
  2043. X    initerrors();
  2044. X    (void) dictinsert(builtin_dict, "None", None);
  2045. X}
  2046. EOF
  2047. fi
  2048. if test -s 'src/cgen'
  2049. then echo '*** I will not over-write existing file src/cgen'
  2050. else
  2051. echo 'x - src/cgen'
  2052. sed 's/^X//' > 'src/cgen' << 'EOF'
  2053. X# Python script to parse cstubs file for gl and generate C stubs.
  2054. X# usage: python cgen <cstubs >glmodule.c
  2055. X#
  2056. X# XXX BUG return arrays generate wrong code
  2057. X# XXX need to change error returns into gotos to free mallocked arrays
  2058. X
  2059. X
  2060. Ximport string
  2061. Ximport sys
  2062. X
  2063. X
  2064. X# Function to print to stderr
  2065. X#
  2066. Xdef err(args):
  2067. X    savestdout = sys.stdout
  2068. X    try:
  2069. X        sys.stdout = sys.stderr
  2070. X        for i in args:
  2071. X            print i,
  2072. X        print
  2073. X    finally:
  2074. X        sys.stdout = savestdout
  2075. X
  2076. X
  2077. X# The set of digits that form a number
  2078. X#
  2079. Xdigits = '0123456789'
  2080. X
  2081. X
  2082. X# Function to extract a string of digits from the front of the string.
  2083. X# Returns the leading string of digits and the remaining string.
  2084. X# If no number is found, returns '' and the original string.
  2085. X#
  2086. Xdef getnum(s):
  2087. X    n = ''
  2088. X    while s and s[0] in digits:
  2089. X        n = n + s[0]
  2090. X        s = s[1:]
  2091. X    return n, s
  2092. X
  2093. X
  2094. X# Function to check if a string is a number
  2095. X#
  2096. Xdef isnum(s):
  2097. X    if not s: return 0
  2098. X    for c in s:
  2099. X        if not c in digits: return 0
  2100. X    return 1
  2101. X
  2102. X
  2103. X# Allowed function return types
  2104. X#
  2105. Xreturn_types = ['void', 'short', 'long']
  2106. X
  2107. X
  2108. X# Allowed function argument types
  2109. X#
  2110. Xarg_types = ['char', 'string', 'short', 'float', 'long', 'double']
  2111. X
  2112. X
  2113. X# Need to classify arguments as follows
  2114. X#    simple input variable
  2115. X#    simple output variable
  2116. X#    input array
  2117. X#    output array
  2118. X#    input giving size of some array
  2119. X#
  2120. X# Array dimensions can be specified as follows
  2121. X#    constant
  2122. X#    argN
  2123. X#    constant * argN
  2124. X#    retval
  2125. X#    constant * retval
  2126. X#
  2127. X# The dimensions given as constants * something are really
  2128. X# arrays of points where points are 2- 3- or 4-tuples
  2129. X#
  2130. X# We have to consider three lists:
  2131. X#    python input arguments
  2132. X#    C stub arguments (in & out)
  2133. X#    python output arguments (really return values)
  2134. X#
  2135. X# There is a mapping from python input arguments to the input arguments
  2136. X# of the C stub, and a further mapping from C stub arguments to the
  2137. X# python return values
  2138. X
  2139. X
  2140. X# Exception raised by checkarg() and generate()
  2141. X#
  2142. Xarg_error = 'bad arg'
  2143. X
  2144. X
  2145. X# Function to check one argument.
  2146. X# Arguments: the type and the arg "name" (really mode plus subscript).
  2147. X# Raises arg_error if something's wrong.
  2148. X# Return type, mode, factor, rest of subscript; factor and rest may be empty.
  2149. X#
  2150. Xdef checkarg(type, arg):
  2151. X    #
  2152. X    # Turn "char *x" into "string x".
  2153. X    #
  2154. X    if type = 'char' and arg[0] = '*':
  2155. X        type = 'string'
  2156. X        arg = arg[1:]
  2157. X    #
  2158. X    # Check that the type is supported.
  2159. X    #
  2160. X    if type not in arg_types:
  2161. X        raise arg_error, ('bad type', type)
  2162. X    #
  2163. X    # Split it in the mode (first character) and the rest.
  2164. X    #
  2165. X    mode, rest = arg[:1], arg[1:]
  2166. X    #
  2167. X    # The mode must be 's' for send (= input) or 'r' for return argument.
  2168. X    #
  2169. X    if mode not in ('r', 's'):
  2170. X        raise arg_error, ('bad arg mode', mode)
  2171. X    #
  2172. X    # Is it a simple argument: if so, we are done.
  2173. X    #
  2174. X    if not rest:
  2175. X        return type, mode, '', ''
  2176. X    #    
  2177. X    # Not a simple argument; must be an array.
  2178. X    # The 'rest' must be a subscript enclosed in [ and ].
  2179. X    # The subscript must be one of the following forms,
  2180. X    # otherwise we don't handle it (where N is a number):
  2181. X    #    N
  2182. X    #    argN
  2183. X    #    retval
  2184. X    #    N*argN
  2185. X    #    N*retval
  2186. X    #
  2187. X    if rest[:1] <> '[' or rest[-1:] <> ']':
  2188. X        raise arg_error, ('subscript expected', rest)
  2189. X    sub = rest[1:-1]
  2190. X    #
  2191. X    # Is there a leading number?
  2192. X    #
  2193. X    num, sub = getnum(sub)
  2194. X    if num:
  2195. X        # There is a leading number
  2196. X        if not sub:
  2197. X            # The subscript is just a number
  2198. X            return type, mode, num, ''
  2199. X        if sub[:1] = '*':
  2200. X            # There is a factor prefix
  2201. X            sub = sub[1:]
  2202. X        else:
  2203. X            raise arg_error, ('\'*\' expected', sub)
  2204. X    if sub = 'retval':
  2205. X        # size is retval -- must be a reply argument
  2206. X        if mode <> 'r':
  2207. X            raise arg_error, ('non-r mode with [retval]', mode)
  2208. X    elif sub[:3] <> 'arg' or not isnum(sub[3:]):
  2209. X        raise arg_error, ('bad subscript', sub)
  2210. X    #
  2211. X    return type, mode, num, sub
  2212. X
  2213. X
  2214. X# List of functions for which we have generated stubs
  2215. X#
  2216. Xfunctions = []
  2217. X
  2218. X
  2219. X# Generate the stub for the given function, using the database of argument
  2220. X# information build by successive calls to checkarg()
  2221. X#
  2222. Xdef generate(type, func, database):
  2223. X    #
  2224. X    # Check that we can handle this case:
  2225. X    # no variable size reply arrays yet
  2226. X    #
  2227. X    n_in_args = 0
  2228. X    n_out_args = 0
  2229. X    #
  2230. X    for a_type, a_mode, a_factor, a_sub in database:
  2231. X        if a_mode = 's':
  2232. X            n_in_args = n_in_args + 1
  2233. X        elif a_mode = 'r':
  2234. X            n_out_args = n_out_args + 1
  2235. X        else:
  2236. X            # Can't happen
  2237. X            raise arg_error, ('bad a_mode', a_mode)
  2238. X        if (a_mode = 'r' and a_sub) or a_sub = 'retval':
  2239. X            e = 'Function', func, 'too complicated:'
  2240. X            err(e + (a_type, a_mode, a_factor, a_sub))
  2241. X            print '/* XXX Too complicated to generate code for */'
  2242. X            return
  2243. X    #
  2244. X    functions.append(func)
  2245. X    #
  2246. X    # Stub header
  2247. X    #
  2248. X    print
  2249. X    print 'static object *'
  2250. X    print 'gl_' + func + '(self, args)'
  2251. X    print '\tobject *self;'
  2252. X    print '\tobject *args;'
  2253. X    print '{'
  2254. X    #
  2255. X    # Declare return value if any
  2256. X    #
  2257. X    if type <> 'void':
  2258. X        print '\t' + type, 'retval;'
  2259. X    #
  2260. X    # Declare arguments
  2261. X    #
  2262. X    for i in range(len(database)):
  2263. X        a_type, a_mode, a_factor, a_sub = database[i]
  2264. X        print '\t' + a_type,
  2265. X        if a_sub:
  2266. X            print '*',
  2267. X        print 'arg' + `i+1`,
  2268. X        if a_factor and not a_sub:
  2269. X            print '[', a_factor, ']',
  2270. X        print ';'
  2271. X    #
  2272. X    # Find input arguments derived from array sizes
  2273. X    #
  2274. X    for i in range(len(database)):
  2275. X        a_type, a_mode, a_factor, a_sub = database[i]
  2276. X        if a_mode = 's' and a_sub[:3] = 'arg' and isnum(a_sub[3:]):
  2277. X            # Sending a variable-length array
  2278. X            n = eval(a_sub[3:])
  2279. X            if 1 <= n <= len(database):
  2280. X                b_type, b_mode, b_factor, b_sub = database[n-1]
  2281. X                if b_mode = 's':
  2282. X                    database[n-1] = b_type, 'i', a_factor, `i`
  2283. X                    n_in_args = n_in_args - 1
  2284. X    #
  2285. X    # Assign argument positions in the Python argument list
  2286. X    #
  2287. X    in_pos = []
  2288. X    i_in = 0
  2289. X    for i in range(len(database)):
  2290. X        a_type, a_mode, a_factor, a_sub = database[i]
  2291. X        if a_mode = 's':
  2292. X            in_pos.append(i_in)
  2293. X            i_in = i_in + 1
  2294. X        else:
  2295. X            in_pos.append(-1)
  2296. X    #
  2297. X    # Get input arguments
  2298. X    #
  2299. X    for i in range(len(database)):
  2300. X        a_type, a_mode, a_factor, a_sub = database[i]
  2301. X        if a_mode = 'i':
  2302. X            #
  2303. X            # Implicit argument;
  2304. X            # a_factor is divisor if present,
  2305. X            # a_sub indicates which arg (`database index`)
  2306. X            #
  2307. X            j = eval(a_sub)
  2308. X            print '\tif',
  2309. X            print '(!geti' + a_type + 'arraysize(args,',
  2310. X            print `n_in_args` + ',',
  2311. X            print `in_pos[j]` + ',',
  2312. X            print '&arg' + `i+1` + '))'
  2313. X            print '\t\treturn NULL;'
  2314. X            if a_factor:
  2315. X                print '\targ' + `i+1`,
  2316. X                print '= arg' + `i+1`,
  2317. X                print '/', a_factor + ';'
  2318. X        elif a_mode = 's':
  2319. X            if a_sub: # Allocate memory for varsize array
  2320. X                print '\tif ((arg' + `i+1`, '=',
  2321. X                print 'NEW(' + a_type + ',',
  2322. X                if a_factor: print a_factor, '*',
  2323. X                print a_sub, ')) == NULL)'
  2324. X                print '\t\treturn err_nomem();'
  2325. X            print '\tif',
  2326. X            if a_factor or a_sub: # Get a fixed-size array array
  2327. X                print '(!geti' + a_type + 'array(args,',
  2328. X                print `n_in_args` + ',',
  2329. X                print `in_pos[i]` + ',',
  2330. X                if a_factor: print a_factor,
  2331. X                if a_factor and a_sub: print '*',
  2332. X                if a_sub: print a_sub,
  2333. X                print ', arg' + `i+1` + '))'
  2334. X            else: # Get a simple variable
  2335. X                print '(!geti' + a_type + 'arg(args,',
  2336. X                print `n_in_args` + ',',
  2337. X                print `in_pos[i]` + ',',
  2338. X                print '&arg' + `i+1` + '))'
  2339. X            print '\t\treturn NULL;'
  2340. X    #
  2341. X    # Begin of function call
  2342. X    #
  2343. X    if type <> 'void':
  2344. X        print '\tretval =', func + '(',
  2345. X    else:
  2346. X        print '\t' + func + '(',
  2347. X    #
  2348. X    # Argument list
  2349. X    #
  2350. X    for i in range(len(database)):
  2351. X        if i > 0: print ',',
  2352. X        a_type, a_mode, a_factor, a_sub = database[i]
  2353. X        if a_mode = 'r' and not a_factor:
  2354. X            print '&',
  2355. X        print 'arg' + `i+1`,
  2356. X    #
  2357. X    # End of function call
  2358. X    #
  2359. X    print ');'
  2360. X    #
  2361. X    # Free varsize arrays
  2362. X    #
  2363. X    for i in range(len(database)):
  2364. X        a_type, a_mode, a_factor, a_sub = database[i]
  2365. X        if a_mode = 's' and a_sub:
  2366. X            print '\tDEL(arg' + `i+1` + ');'
  2367. X    #
  2368. X    # Return
  2369. X    #
  2370. X    if n_out_args:
  2371. X        #
  2372. X        # Multiple return values -- construct a tuple
  2373. X        #
  2374. X        if type <> 'void':
  2375. X            n_out_args = n_out_args + 1
  2376. X        if n_out_args = 1:
  2377. X            for i in range(len(database)):
  2378. X                a_type, a_mode, a_factor, a_sub = database[i]
  2379. X                if a_mode = 'r':
  2380. X                    break
  2381. X            else:
  2382. X                raise arg_error, 'expected r arg not found'
  2383. X            print '\treturn',
  2384. X            print mkobject(a_type, 'arg' + `i+1`) + ';'
  2385. X        else:
  2386. X            print '\t{ object *v = newtupleobject(',
  2387. X            print n_out_args, ');'
  2388. X            print '\t  if (v == NULL) return NULL;'
  2389. X            i_out = 0
  2390. X            if type <> 'void':
  2391. X                print '\t  settupleitem(v,',
  2392. X                print `i_out` + ',',
  2393. X                print mkobject(type, 'retval') + ');'
  2394. X                i_out = i_out + 1
  2395. X            for i in range(len(database)):
  2396. X                a_type, a_mode, a_factor, a_sub = database[i]
  2397. X                if a_mode = 'r':
  2398. X                    print '\t  settupleitem(v,',
  2399. X                    print `i_out` + ',',
  2400. X                    s = mkobject(a_type, 'arg' + `i+1`)
  2401. X                    print s + ');'
  2402. X                    i_out = i_out + 1
  2403. X            print '\t  return v;'
  2404. X            print '\t}'
  2405. X    else:
  2406. X        #
  2407. X        # Simple function return
  2408. X        # Return None or return value
  2409. X        #
  2410. X        if type = 'void':
  2411. X            print '\tINCREF(None);'
  2412. X            print '\treturn None;'
  2413. X        else:
  2414. X            print '\treturn', mkobject(type, 'retval') + ';'
  2415. X    #
  2416. X    # Stub body closing brace
  2417. X    #
  2418. X    print '}'
  2419. X
  2420. X
  2421. X# Subroutine to return a function call to mknew<type>object(<arg>)
  2422. X#
  2423. Xdef mkobject(type, arg):
  2424. X    return 'mknew' + type + 'object(' + arg + ')'
  2425. X
  2426. X
  2427. X# Input line number
  2428. Xlno = 0
  2429. X
  2430. X
  2431. X# Input is divided in two parts, separated by a line containing '%%'.
  2432. X#    <part1>        -- literally copied to stdout
  2433. X#    <part2>        -- stub definitions
  2434. X
  2435. X# Variable indicating the current input part.
  2436. X#
  2437. Xpart = 1
  2438. X
  2439. X# Main loop over the input
  2440. X#
  2441. Xwhile 1:
  2442. X    try:
  2443. X        line = raw_input()
  2444. X    except EOFError:
  2445. X        break
  2446. X    #
  2447. X    lno = lno+1
  2448. X    words = string.split(line)
  2449. X    #
  2450. X    if part = 1:
  2451. X        #
  2452. X        # In part 1, copy everything literally
  2453. X        # except look for a line of just '%%'
  2454. X        #
  2455. X        if words = ['%%']:
  2456. X            part = part + 1
  2457. X        else:
  2458. X            #
  2459. X            # Look for names of manually written
  2460. X            # stubs: a single percent followed by the name
  2461. X            # of the function in Python.
  2462. X            # The stub name is derived by prefixing 'gl_'.
  2463. X            #
  2464. X            if words and words[0][0] = '%':
  2465. X                func = words[0][1:]
  2466. X                if (not func) and words[1:]:
  2467. X                    func = words[1]
  2468. X                if func:
  2469. X                    functions.append(func)
  2470. X            else:
  2471. X                print line
  2472. X    elif not words:
  2473. X        pass            # skip empty line
  2474. X    elif words[0] = '#include':
  2475. X        print line
  2476. X    elif words[0][:1] = '#':
  2477. X        pass            # ignore comment
  2478. X    elif words[0] not in return_types:
  2479. X        err('Line', lno, ': bad return type :', words[0])
  2480. X    elif len(words) < 2:
  2481. X        err('Line', lno, ': no funcname :', line)
  2482. X    else:
  2483. X        if len(words) % 2 <> 0:
  2484. X            err('Line', lno, ': odd argument list :', words[2:])
  2485. X        else:
  2486. X            database = []
  2487. X            try:
  2488. X                for i in range(2, len(words), 2):
  2489. X                    x = checkarg(words[i], words[i+1])
  2490. X                    database.append(x)
  2491. X                print
  2492. X                print '/*',
  2493. X                for w in words: print w,
  2494. X                print '*/'
  2495. X                generate(words[0], words[1], database)
  2496. X            except arg_error, msg:
  2497. X                err('Line', lno, ':', msg)
  2498. X
  2499. X
  2500. Xprint
  2501. Xprint 'static struct methodlist gl_methods[] = {'
  2502. Xfor func in functions:
  2503. X    print '\t{"' + func + '", gl_' + func + '},'
  2504. Xprint '\t{NULL, NULL} /* Sentinel */'
  2505. Xprint '};'
  2506. Xprint
  2507. Xprint 'initgl()'
  2508. Xprint '{'
  2509. Xprint '\tinitmodule("gl", gl_methods);'
  2510. Xprint '}'
  2511. EOF
  2512. fi
  2513. echo 'Part 10 out of 21 of pack.out complete.'
  2514. exit 0
  2515.