home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / abc / part12 < prev    next >
Encoding:
Internet Message Format  |  1991-01-08  |  54.4 KB

  1. Subject:  v23i091:  ABC interactive programming environment, Part12/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: f303971b 540bb072 9f5a05fb 50aff956
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 91
  8. Archive-name: abc/part12
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  abc/Makefile.unix abc/boot/grammar.abc abc/btr/i1tex.c
  17. #   abc/lin/i1tlt.c
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:28:04 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 12 (of 25)."'
  22. if test -f 'abc/Makefile.unix' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'abc/Makefile.unix'\"
  24. else
  25.   echo shar: Extracting \"'abc/Makefile.unix'\" \(13343 characters\)
  26.   sed "s/^X//" >'abc/Makefile.unix' <<'END_OF_FILE'
  27. X#######################################################################
  28. X#                                                                     #
  29. X#                 Makefile for ABC system under unix.                 #
  30. X#                                                                     #
  31. X#######################################################################
  32. X
  33. X# --- Some make's only make love with the Bourne shell ---
  34. X#
  35. X
  36. XSHELL=    /bin/sh
  37. X
  38. X
  39. X# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  40. X# +++ Start of editable macro definitions; filled in by ./Setup      +++
  41. X# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  42. X
  43. X# --- pass make options ---
  44. X#
  45. X# On 4.{23}BSD the macro $(MFLAGS) is set by make to the collection of
  46. X# command line options (such as -k, -i) and passed to make in subdirectories.
  47. X# For System V use $(MAKEFLAGS). Otherwise just fill in 'make'.
  48. X
  49. XMAKE=    make $(MFLAGS)
  50. X
  51. X
  52. X# --- Where to install the stuff ---
  53. X#
  54. X# These should all be absolute pathnames.
  55. X
  56. X# destination directory for binaries 'abc' and 'abckeys':
  57. X
  58. XDESTABC=/usr/new
  59. X
  60. X# destination directory for auxiliary data files:
  61. X
  62. XDESTLIB=/usr/new/lib/abc
  63. X
  64. X# destination directory for 'abc.1' manual page:
  65. X
  66. XDESTMAN=/usr/man/mann
  67. X
  68. X# local destination if you cross-compile; empty otherwise:
  69. X
  70. XDESTROOT=
  71. X# you should first generate uhdrs/config.h remotely;
  72. X# see 'make config' below.
  73. X
  74. X
  75. X# --- Software floating point needed? ---
  76. X
  77. XFLOAT=
  78. X
  79. X
  80. X# --- Flags to the C compiler ---
  81. X
  82. XDEFS=    -DNDEBUG
  83. XCFLAGS= -O $(FLOAT) $(DEFS)
  84. X
  85. X
  86. X# --- Flags to the loader ---
  87. X
  88. XLDFLAGS=
  89. X
  90. X
  91. X# --- Specify termcap or termlib library ---
  92. X#
  93. X# Set TERMLIB to the appropriate termcap or termlib library specification
  94. X# (either -lxxx option or absolute pathname) if your system has one.
  95. X# Otherwise leave TERMLIB empty and remove the comment symbols before
  96. X# the definitions of OWNTLIB, KOWNTLIB and OWNTBASE to install the
  97. X# public domain version from ./tc.
  98. X
  99. XTERMLIB= -ltermcap
  100. X
  101. X#OWNTLIB= libtermcap.a
  102. X#KOWNTLIB= ../libtermcap.a
  103. X#OWNTBASE= termcap
  104. X
  105. X
  106. X# --- Libraries for editor-interpreter 'abc' ---
  107. X
  108. XLIBS=    -lm $(TERMLIB) $(OWNTLIB)
  109. X
  110. X
  111. X# --- Libraries for utility 'abckeys' ---
  112. X
  113. XKLIBS=    $(TERMLIB) $(KOWNTLIB)
  114. X
  115. X
  116. X# --- How to generate dependency information for make ---
  117. X#
  118. X# Set MKDEP to $(CC) -M $(DEFS) or to ../scripts/mkdep $(DEFS).
  119. X# 'cc -M' is a 4.2BSD-only feature which causes the C preprocessor
  120. X# to output a list of dependencies that is directly usable by make.
  121. X# This can be simulated exactly by piping the output of your preprocessor
  122. X# through the shell script ./scripts/mkdep.
  123. X# Check the comments there to see if it needs polishing for your system.
  124. X
  125. XMKDEP=    $(CC) -M $(DEFS)
  126. X
  127. X
  128. X# --- names of makefiles and dependency-files in subdirectories ---
  129. X#
  130. X# Only change in case of problems; consult ./Problems.
  131. X
  132. XMF=    Mf
  133. XDEP=    Dep
  134. X
  135. X
  136. X# --- name of messages file (holding abc's error messages) ---
  137. X#
  138. X# Change to MESSAGES=abc.mse in case you had to add or change error messages
  139. X# in the source; then, use 'make messages' to create a new messages file
  140. X# from the source.
  141. X# If you want the error messages in Swahili, translate abc.msg, put the result
  142. X# in abc.swahili, and set MESSAGES=abc.swahili.
  143. X# In both cases use 'make all' to incorporate the new messages file in abc.
  144. X# You might also update the FILES section of the manual ./abc.1.
  145. X
  146. XMESSAGES=abc.msg
  147. X
  148. X
  149. X# --- name of help file (used in helpblurb after keybindings) ---
  150. X#
  151. X# This file contains exactly the abc.1 manual entry.
  152. X# If you translate it, use another name and fill it in here;
  153. X# the changed name will be filled in properly by 'make all'.
  154. X# Also update ./abc.1 in this case.
  155. X
  156. XHELP=abc.hlp
  157. X
  158. X
  159. X# +++++++++++++++++++++++++++++++++++++++++
  160. X# +++ End of editable macro definitions +++
  161. X# +++++++++++++++++++++++++++++++++++++++++
  162. X#
  163. X# The remaining macro definitions should only have to be edited
  164. X# if you make very drastic changes.
  165. X
  166. X# --- Include flags to the C compiler for editor and interpreter directories ---
  167. X
  168. XBINCL=    -I../bhdrs -I../uhdrs
  169. XEINCL=    -I../bhdrs -I../ehdrs -I../uhdrs -I../btr
  170. XIINCL=    -I../bhdrs -I../ihdrs -I../uhdrs
  171. XUINCL=    -I../bhdrs -I../ehdrs -I../ihdrs -I../uhdrs
  172. X
  173. X# --- Editor and interpreter directories ---
  174. X
  175. XCDIRS=    b bed bint1 bint2 bint3 btr unix stc bio
  176. X
  177. XBDIRS=    b
  178. XEDIRS=    bed
  179. XIDIRS=    bint1 bint2 bint3 btr stc bio
  180. XUDIRS=    unix
  181. X
  182. X# --- Editor and interpreter files ---
  183. X
  184. XBOBJS=    b/*.o
  185. XEOBJS=    bed/*.o
  186. XIOBJS=    bint1/*.o bint2/*.o bint3/*.o btr/*.o stc/*.o bio/*.o
  187. XUOBJS=    unix/*.o
  188. X
  189. XBSRCS=    b/*.c
  190. XESRCS=    bed/*.c
  191. XISRCS=    bint1/*.c bint2/*.c bint3/*.c btr/*.c stc/*.c bio/*.c
  192. XUSRCS=    unix/*.c
  193. X
  194. XBHDRS=    bhdrs/*.h
  195. XEHDRS=    ehdrs/*.h
  196. XIHDRS=    ihdrs/*.h btr/*.h bio/*.h
  197. XUHDRS=    uhdrs/*.h
  198. X
  199. X# --- Preliminary dependencies (do not change for Unix) ---
  200. X
  201. XCONFIG=    uhdrs/config.h
  202. XOSHDIR= uhdrs
  203. X
  204. XDEST=    uhdrs/dest.h
  205. X
  206. X# --- Stuff for programmers ---
  207. X
  208. XLINT=        lint
  209. X# change the next one to -p for ATT System V
  210. XLINTFLAGS=    -abhxp
  211. XLINCL=        -Ibhdrs -Iehdrs -Iihdrs -Iuhdrs -Ibtr
  212. X
  213. XTAGDIRS=b bed bint1 bint2 bint3 btr stc bio unix keys bhdrs ehdrs ihdrs uhdrs
  214. X
  215. X
  216. X# ---------------------------------------------------------------------
  217. X# --- make makefiles: construct trivial makefiles in subdirectories ---
  218. X# ----------------------------------------------------------------------
  219. X#
  220. X# This constructs trivial makefiles called 'Mf' in relevant subdirectories.
  221. X# You can use distributed makefiles called 'MF' if this fails.
  222. X# See ./Problems for details.
  223. X
  224. Xmakefiles:
  225. X    for i in $(CDIRS); do \
  226. X        ( cd $$i; echo all: *.c | sed 's/\.c/.o/g' >Mf ) done
  227. X    @./ch_makefiles "$(MF)"
  228. X
  229. X# No automatic makefile in ./keys. Edit that one yourself if need be.
  230. X
  231. X
  232. X# ----------------------------------------------------------------------------
  233. X# --- make depend: construct makefiles with dependencies in subdirectories ---
  234. X# ----------------------------------------------------------------------------
  235. X#
  236. X# This constructs additional makefiles called 'Dep' in subdirectories
  237. X# containing the dependency information.
  238. X# If it fails you can likewise use distributed ones called 'DEP'.
  239. X# See ./Problems.
  240. X
  241. Xdepend: $(CONFIG) $(DEST) bdep edep idep udep kdep
  242. X    @./ch_depend "$(DEP)"
  243. X
  244. X# The file $(DEST) communicates the place and names of auxiliary files
  245. X# to the binaries 'abc' and 'abckeys'.
  246. X# It is unconditionally remade for every 'make all' or 'make install'.
  247. X# Here we just make sure it exists.
  248. X
  249. X$(DEST):
  250. X    touch $(DEST)
  251. X
  252. Xbdep:
  253. X    for i in $(BDIRS); do \
  254. X        ( echo $$i; cd $$i; $(MKDEP) $(BINCL) *.c >Dep ) done
  255. X
  256. Xedep:
  257. X    for i in $(EDIRS); do \
  258. X        ( echo $$i; cd $$i; $(MKDEP) $(EINCL) *.c >Dep ) done
  259. X
  260. Xidep:
  261. X    for i in $(IDIRS); do \
  262. X        ( echo $$i; cd $$i; $(MKDEP) $(IINCL) *.c >Dep ) done
  263. X
  264. Xudep:
  265. X    for i in $(UDIRS); do \
  266. X        ( echo $$i; cd $$i; $(MKDEP) $(UINCL) *.c >Dep ) done
  267. X
  268. Xkdep:
  269. X    cd keys; $(MAKE) MKDEP="$(MKDEP)" DEFS="$(DEFS)" depend >Dep
  270. X
  271. X
  272. X# -------------------------------------------
  273. X# ---  make all: make everything locally  ---
  274. X# -------------------------------------------
  275. X#
  276. X# This makes all programs and utilities in the current directory.
  277. X# (Except for the ready-for-use default key definitions files).
  278. X
  279. Xall:    alldest $(CONFIG) abc abckeys $(MESSAGES) $(HELP)
  280. X    @./ch_all "$(MESSAGES)" "$(HELP)" "$(DESTROOT)"
  281. X
  282. X# The target 'alldest' is used to communicate the place of auxiliary files.
  283. X#
  284. X# Dependency on the (non-existent) file "ALWAYS" causes this entry to
  285. X# be (re)made unconditionally. Make won't complain about ALWAYS not being
  286. X# found because there is also a rule referencing it as target at the
  287. X# very end (which actually doesn't make it, but make doesn't care).
  288. X
  289. Xalldest: ALWAYS
  290. X    echo "#define ABCLIB \"`pwd`\"" >$(DEST)
  291. X    echo "#define MESSFILE \"$(MESSAGES)\"" >>$(DEST)
  292. X    echo "#define HELPFILE \"$(HELP)\"" >>$(DEST)
  293. X
  294. X# CONFIG: generate include file with info about the hardware configuration.
  295. X#
  296. X# Special care is taken to remove an incomplete $(CONFIG) if mkconfig
  297. X# fails halfway. Otherwise a subsequent 'make depend' will happily go on.
  298. X
  299. Xconfig: $(CONFIG)
  300. X
  301. X$(CONFIG): mkconfig.c $(OSHDIR)/osconf.h
  302. X    @./ch_config "$(DESTROOT)" "$(CONFIG)"
  303. X    $(CC) -I$(OSHDIR) mkconfig.c -o mkconfig
  304. X    mkconfig >$(CONFIG) || (rm -f $(CONFIG) && exit 1)
  305. X
  306. X# abc: make the executable that is the kernel of the system.
  307. X#
  308. X# The load must be unconditional, since we cannot know whether
  309. X# any of the submakes had to update some subtarget.
  310. X
  311. Xabc:    $(CONFIG) $(BDIRS) $(EDIRS) $(IDIRS) $(UDIRS) \
  312. X        $(OWNTLIB) $(OWNTBASE) ALWAYS
  313. X    $(CC) $(LDFLAGS) $(BOBJS) $(EOBJS) $(IOBJS) $(UOBJS) $(LIBS) -o abc
  314. X
  315. X# Call make for each editor and interpreter subdirectory with proper flags.
  316. X#
  317. X# If a dependency line has more than one item left of the colon, the
  318. X# commands are executed for each of the items, with $@ substituted
  319. X# by the item's name.
  320. X
  321. X$(BDIRS): $(CONFIG) ALWAYS
  322. X    cd $@; $(MAKE) -f $(MF) -f $(DEP) CFLAGS='$(CFLAGS) $(BINCL)' all
  323. X
  324. X$(EDIRS): $(CONFIG) ALWAYS
  325. X    cd $@; $(MAKE) -f $(MF) -f $(DEP) CFLAGS='$(CFLAGS) $(EINCL)' all
  326. X
  327. X$(IDIRS): $(CONFIG) ALWAYS
  328. X    cd $@; $(MAKE) -f $(MF) -f $(DEP) CFLAGS='$(CFLAGS) $(IINCL)' all
  329. X
  330. X$(UDIRS): $(CONFIG) ALWAYS
  331. X    cd $@; $(MAKE) -f $(MF) -f $(DEP) CFLAGS='$(CFLAGS) $(UINCL)' all
  332. X
  333. X# Make new messages file when you have changed any in the source.
  334. X# Note: the Collect and Change scripts can be found in ./scripts.
  335. X# See ./Problems for details.
  336. X
  337. Xmessages: checkmse abc.mse
  338. X
  339. Xcheckmse:
  340. X    @./ch_messages "$(MESSAGES)"
  341. X
  342. Xabc.mse: $(BSRCS) $(ESRCS) $(ISRCS) $(USRCS) \
  343. X        ihdrs/i0err.h ehdrs/erro.h bio/i4bio.h
  344. X    ./scripts/Collect $(BSRCS) $(ESRCS) $(ISRCS) $(USRCS) \
  345. X        ihdrs/i0err.h ehdrs/erro.h bio/i4bio.h >abc.mse
  346. X
  347. Xabc.msg:
  348. X    @echo "Some dwarf has sneaked away the original messages file"
  349. X    @echo "See ./Problems on how to recreate a new one"
  350. X
  351. X# Help file from manual entry.
  352. X# Sorry, the file unix/abc.mac was created from copyrighted material;
  353. X# therefore, it is not in the distribution.
  354. X#
  355. X# #abc.hlp: unix/abc.mac abc.1
  356. X# #    nroff unix/abc.mac abc.1 >abc.help
  357. X# #    (echo "SUMMARY OF SPECIAL ACTIONS"; \
  358. X# #     sed -e '1,/^SUMMARY/d' abc.help; \
  359. X# #     echo " "; \
  360. X# #     sed -e '/^SUMMARY/,$$d' abc.help) >abc.hlp
  361. X# #    rm abc.help
  362. X
  363. X# Make utility 'abckeys' for redefinition of keybindings.
  364. X#
  365. X# The submake will find out whether recompilation is necessary.
  366. X
  367. Xabckeys: $(OWNTLIB) $(OWNTBASE) ALWAYS
  368. X    cd keys; \
  369. X     $(MAKE) -f Makefile -f $(DEP) \
  370. X         CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBS="$(KLIBS)" all
  371. X
  372. X
  373. X# ----------------------------------------------
  374. X# --- make examples: try the ABC interpreter ---
  375. X# ----------------------------------------------
  376. X
  377. Xexamples:
  378. X    @cd ex; DoExamples local
  379. X#    ch_examples is embedded in DoExamples to cope with cross compilation.
  380. X
  381. X
  382. X# ---------------------------------------------------------
  383. X# --- make try_editor: try the ABC editor interactively ---
  384. X# ---------------------------------------------------------
  385. X
  386. Xtry_editor:
  387. X    @cd ex; TryEditor local
  388. X#    ch_tryeditor embedded in TryEditor.
  389. X
  390. X# ---------------------------------------------------------
  391. X# --- make install: install everything in public places ---
  392. X# ---------------------------------------------------------
  393. X#
  394. X# The dependency of 'install' on 'installdest communicates the place
  395. X# and names of auxiliary files to the binaries 'abc' and 'abckeys'.
  396. X# The unconditional submakes of the latter targets causes the
  397. X# proper files to be remade.
  398. X#
  399. X# The directory ukeys contains default keydefinitions files for
  400. X# several terminals.
  401. X
  402. Xinstall: installdest abc abckeys $(MESSAGES) $(HELP)
  403. X    cp abc abckeys $(DESTROOT)$(DESTABC)
  404. X    cp $(MESSAGES) $(HELP) $(DESTROOT)$(DESTLIB)
  405. X    cd ukeys; cp abckeys_* $(DESTROOT)$(DESTLIB)
  406. X    cp abc.1 $(DESTROOT)$(DESTMAN)
  407. X    @./ch_install "$(MESSAGES)" "$(HELP)" \
  408. X        "$(DESTABC)" "$(DESTLIB)" "$(DESTMAN)" "$(DESTROOT)"
  409. X
  410. Xinstalldest: ALWAYS
  411. X    echo "#define ABCLIB \"$(DESTLIB)\"" >$(DEST)
  412. X    echo "#define MESSFILE \"$(MESSAGES)\"" >>$(DEST)
  413. X    echo "#define HELPFILE \"$(HELP)\"" >>$(DEST)
  414. X
  415. X
  416. X# -------------------------------------------------
  417. X# --- Make our own termcap library and database ---
  418. X# -------------------------------------------------
  419. X#
  420. X# For systems that really don't have any termlib-like library
  421. X# this makes our own from public domain sources in ./tc.
  422. X# See ./tc/README for details.
  423. X# This happens automatically if you remove the comment symbols before
  424. X# the definitions of OWNTLIB and OWNTBASE above.
  425. X
  426. Xlibtermcap.a:
  427. X    cd tc; make library
  428. X
  429. Xtermcap:
  430. X    cd tc; make database
  431. X
  432. X
  433. X# -----------------------------------
  434. X# ---  make clean: local cleanup  ---
  435. X# -----------------------------------
  436. X
  437. Xclean:
  438. X    rm -f */*.o mkconfig $(CONFIG) abc abckeys ex/out
  439. X    @./ch_clean "$(MESSAGES)"
  440. X
  441. X
  442. X# -------------------------------------------------
  443. X# ---  make clobber: additional local cleanup   ---
  444. X# -------------------------------------------------
  445. X
  446. X# To be used after 'make makefiles', 'make depend' and/or 'make messages'.
  447. X
  448. Xclobber:
  449. X    rm -f abc.mse */Mf */Dep */tags tags
  450. X
  451. X
  452. X# --------------------------------------
  453. X# ---  Utilities for the programmer  ---
  454. X# --------------------------------------
  455. X
  456. Xmflags:
  457. X    echo MFLAGS="$(MFLAGS)", MAKEFLAGS="$(MAKEFLAGS)"
  458. X
  459. Xlint:    abclint klint
  460. X
  461. Xabclint:
  462. X    $(LINT) $(LINTFLAGS) $(DEFS) $(LINCL) \
  463. X        $(BSRCS) $(ESRCS) $(ISRCS) $(USRCS)
  464. X
  465. Xklint:
  466. X    cd keys; \
  467. X     $(MAKE) LINT="$(LINT)" LINTFLAGS="$(LINTFLAGS)" DEFS="$(DEFS)" lint
  468. X
  469. Xtags:    ALWAYS
  470. X    rm -f tags   # Remove it so it will be remade when an interrupt hits
  471. X    for i in $(TAGDIRS); \
  472. X    do \
  473. X        ( echo $$i; cd $$i; ctags -w *.[ch]; \
  474. X          sed "s,    ,    $$i/," tags \
  475. X        ) \
  476. X    done | sort -o tags
  477. X
  478. X
  479. Xid:    ALWAYS
  480. X    mkid */*.[hc]
  481. X
  482. X
  483. XALWAYS: # Must not exist, but must be mentioned in the makefile
  484. END_OF_FILE
  485.   if test 13343 -ne `wc -c <'abc/Makefile.unix'`; then
  486.     echo shar: \"'abc/Makefile.unix'\" unpacked with wrong size!
  487.   fi
  488.   # end of 'abc/Makefile.unix'
  489. fi
  490. if test -f 'abc/boot/grammar.abc' -a "${1}" != "-c" ; then 
  491.   echo shar: Will not clobber existing file \"'abc/boot/grammar.abc'\"
  492. else
  493.   echo shar: Extracting \"'abc/boot/grammar.abc'\" \(13172 characters\)
  494.   sed "s/^X//" >'abc/boot/grammar.abc' <<'END_OF_FILE'
  495. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1988. */
  496. X/*
  497. X * Grammar for ABC.
  498. X *
  499. X * This file defines a grammar with three distinct grammatical items:
  500. X * classes, Symbols and LEXICALs.
  501. X *    class-names are [a-z][a-z0-9_]*           # lower-case
  502. X *    Symbol-names are [A-Z][a-z][a-z0-9_]*    # First-upper_rest-lower
  503. X *    LEXICAL-names are [A_Z][A_Z][A_Z0-9_]*  # ALL_UPPER
  504. X * (note: the second char of a Symbol or lexical MUST be alphabetic)
  505. X *
  506. X * A Symbol definition looks like:
  507. X *    Put: "PUT ", expression, " IN ", address.
  508. X * e.g. a sequence of "Fixed text" between quotes, alternated with class- or
  509. X * LEXICAL-names, separated by comma's, ending with a point;
  510. X * between names, any of the "TEXT" items may be missing, 
  511. X * but between "TEXT"'s a name must be there;
  512. X * there may be no more than MAXCHILD (4, see main.h) names,
  513. X * and no more than MAXCHILD+1 "TEXT"'s;
  514. X * the text's "\n", "\t" and "\b" are used in this grammar for ABC's
  515. X * newline, increase-indentation and decrease-indentation, respectively.
  516. X *
  517. X * A class definition looks like:
  518. X *    optional_comment: Optional; COMMENT.
  519. X * using only Symbol-names or LEXICAL-names, seperated by comma's and
  520. X * ending in a point.
  521. X * It denotes a sequence of possible alternatives for this class.
  522. X *
  523. X * The Symbol Optional is defined by mktable at the end of the grammar,
  524. X * where the ABC editor expects it, as:
  525. X *    Optional: .
  526. X * If it is used in the alternative list of a class definition, it must be
  527. X * the first one.
  528. X *
  529. X * A LEXICAL definition looks like:
  530. X *    NUMBER: "0123456789", "0123456789".
  531. X * where the first (C-)string denotes the characters this LEXICAL item can
  532. X * start with, and the second string the ones that may be used in a
  533. X * continuation.
  534. X * If the first character of a string is '^', it means: 
  535. X *    'any character not matching any of the following in this string'.
  536. X *
  537. X * Since mktable will generate definitions to "envelop" the LEXICALS,
  538. X * one should not use the corresponding Symbol name, e.g. Rawinput.
  539. X * (to prevent clashes in the produced header-file); nor the class-names
  540. X * e.g. rawinput or rawinput-body (just for readability:-).
  541. X *  
  542. X * Any names longer than 100 characters are silently truncated.
  543. X *  (if in urgent need however, see NAMELEN in main.h)
  544. X *
  545. X * All Symbol-names and class-names must be defined in a definition.
  546. X *
  547. X * The above rules are checked by 'mktable'.
  548. X *
  549. X *
  550. X * BUT not directly on this file:
  551. X *
  552. X * We use the C preprocessor (cc -E) to collect all KEYWORDS of ABC in
  553. X * a single file 'lang.h'. This way you can easily make a Dutch version:-).
  554. X * (But also change ../ihdrs/i0lan.h!-).
  555. X * This changes all "TEXT"-items in Symbol-definitions into R_NAME's.
  556. X *
  557. X * A second use of the preprocessor is in #defining frequently occuring
  558. X * lists of alternative Symbols in class-definitions.
  559. X * To make the grammar more readable, we only use capitals for the name
  560. X * of such a list, and start it with A_ (which we never do for LEXICALS).
  561. X * (This convention is not enforced by the parser in 'mktable'!)
  562. X *
  563. X * A third corrollary of the use of the preprocessor is that you can
  564. X * use C-comments for comments.
  565. X * (In addition, 'mktable' ignores all lines starting with '#', and
  566. X * everything between a point ending a definition and the end of the line.)
  567. X *
  568. X *
  569. X * WARNING: parts of the ABC editor depend on this specific grammar;
  570. X * if you change anything, you might have to change part of the editor too.
  571. X */
  572. X
  573. X#include "lang.h"
  574. X
  575. X/*
  576. X * Root symbol:
  577. X * (since the ABC editor cannot stand zero's for a symbol in an 
  578. X *  alternative sequence \\ all those while(!*cp) 's \\ this must
  579. X *  be the first Symbol definition, and may not be referenced);
  580. X * (anyway, it's only a dummy, that the ABC editor will overwrite
  581. X *  with setroot()).
  582. X */
  583. X
  584. XRootsymbol: imm_cmd.
  585. X
  586. X/*
  587. X * Lexical symbols
  588. X */
  589. X
  590. XNAME:    "abcdefghijklmnopqrstuvwxyz",
  591. X    "abcdefghijklmnopqrstuvwxyz0123456789'\".".
  592. XKEYWORD:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  593. X    "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'\".".
  594. XNUMBER: "0123456789.", "0123456789.".
  595. XCOMMENT: "\\", "^".
  596. XTEXT1: "^'`", "^'`".
  597. XTEXT2: "^\"`", "^\"`".
  598. XOPERATOR: "+-*/#^~@|<=>", "".
  599. XRAWINPUT: "^", "^".
  600. XSUGGESTION: "", "".
  601. XSUGGHOWNAME: "", "".
  602. X/* For the latter two see comment at the bottom. */
  603. X
  604. X/*
  605. X * Expressions
  606. X */
  607. X
  608. X#define A_DISPLAY List_or_table_display; Text1_display; Text2_display
  609. X#define A_PRIMARY Sel_expr; NAME; NUMBER; Compound; A_DISPLAY
  610. X#define A_SINGLE_EXPR Blocked; Grouped; OPERATOR; A_PRIMARY
  611. X
  612. Xexpression: Collateral; A_SINGLE_EXPR.
  613. Xoptional_expression: Optional; Collateral; A_SINGLE_EXPR.
  614. XCollateral: single_expression, ", ", expression.
  615. XCompound: "(", coll_test, ")".     /* see comment on ambiguity of '(' below */
  616. Xsingle_expression: A_SINGLE_EXPR.
  617. X
  618. XBlocked: block, group.
  619. Xblock: OPERATOR; A_PRIMARY.
  620. XGrouped: group, " ", single_expression.
  621. Xgroup: Blocked; OPERATOR; A_PRIMARY.
  622. X
  623. Xprimary: A_PRIMARY.
  624. XSel_expr: primary, "[", expression, "]".
  625. X
  626. XList_or_table_display: "{", optional_list_or_table_filler_series, "}".
  627. Xoptional_list_or_table_filler_series:
  628. X    Optional; List_filler_series; A_SINGLE_EXPR;
  629. X        Table_filler_series; Table_filler.
  630. XList_filler_series: list_filler, "; ", list_filler_series_tail.
  631. Xlist_filler_series_tail: A_SINGLE_EXPR; List_filler_series.
  632. Xlist_filler: A_SINGLE_EXPR.
  633. XTable_filler_series: table_filler, "; ", table_filler_series_tail.
  634. Xtable_filler: Table_filler.
  635. Xtable_filler_series_tail: Table_filler_series; Table_filler.
  636. XTable_filler: "[", expression, "]: ", single_expression.
  637. X
  638. XText1_display: "'", txt1, "'".
  639. Xtxt1: Optional; TEXT1; Conversion; Text1_plus.
  640. XText1_plus: text1_conv, text1_next.
  641. Xtext1_conv: TEXT1; Conversion.
  642. Xtext1_next: TEXT1; Conversion; Text1_plus.
  643. X
  644. XText2_display: "\"", txt2, "\"".
  645. Xtxt2: Optional; TEXT2; Conversion; Text2_plus.
  646. XText2_plus: text2_conv, text2_next.
  647. Xtext2_conv: TEXT2; Conversion.
  648. Xtext2_next: TEXT2; Conversion; Text2_plus.
  649. X
  650. XConversion: "`", optional_expression, "`".
  651. X
  652. X/*
  653. X * Addresses
  654. X */
  655. X
  656. X#define A_SINGLE_ADDRESS NAME; Compound_address; Selection; Behead; Curtail
  657. X#define r_expr group
  658. X
  659. Xaddress: Multiple_address; A_SINGLE_ADDRESS.
  660. XMultiple_address: single_address, ", ", address.
  661. Xsingle_address: A_SINGLE_ADDRESS.
  662. XCompound_address: "(", address, ")".
  663. X
  664. XSelection: address, "[", expression, "]".
  665. XBehead: address, "@", r_expr.
  666. XCurtail: address, "|", r_expr.
  667. X
  668. X/* namings are addresses with only NAME's */
  669. X#define A_NAMING Multiple_naming; NAME; Compound_naming 
  670. Xnaming: A_NAMING.
  671. XMultiple_naming: single_naming, ", ", naming.
  672. Xsingle_naming: NAME; Compound_naming.
  673. XCompound_naming: "(", naming, ")".
  674. X
  675. X
  676. X/*
  677. X * Tests
  678. X */
  679. X
  680. X#define A_NOT_or_QUANT Not; Some_in; Each_in; No_in
  681. X
  682. Xtest: A_NOT_or_QUANT; And; Or; A_SINGLE_EXPR.
  683. Xe_test: Else_kw; A_NOT_or_QUANT; And; Or; A_SINGLE_EXPR.
  684. XElse_kw: R_ELSE.
  685. X#define t_test single_expression
  686. Xr_test: A_NOT_or_QUANT; A_SINGLE_EXPR.
  687. Xcoll_test: Collateral; A_NOT_or_QUANT; And; Or; A_SINGLE_EXPR.
  688. X/*
  689. X *  This means that a compound expression may in fact contain
  690. X *  a `collateral test', e.g. (a AND b, c AND d).
  691. X *  Of course, this is illegal in ABC; but I couldn't solve the
  692. X *  ambiguity of `(' where a test is expected otherwise;
  693. X *  this may start a parenthesized test or a compound expression;
  694. X *  the latter may be followed by more expression fragments,
  695. X *  the first may not.
  696. X */
  697. X
  698. XNot: R_NOT, r_test.
  699. XSome_in: R_SOME, naming, R_IN_quant, single_expression, R_HAS, r_test.
  700. XEach_in: R_EACH, naming, R_IN_quant, single_expression,  R_HAS, r_test.
  701. XNo_in: R_NO, naming, R_IN_quant, single_expression,  R_HAS, r_test.
  702. X
  703. XAnd: t_test, " ", and.
  704. XOr: t_test, " ", or.
  705. Xand: And_kw.
  706. Xor: Or_kw.
  707. XAnd_kw: R_AND, and_test.
  708. XOr_kw: R_OR, or_test.
  709. Xand_test: A_NOT_or_QUANT; And; A_SINGLE_EXPR.
  710. Xor_test: A_NOT_or_QUANT; Or; A_SINGLE_EXPR.
  711. X
  712. X/*
  713. X * Commands
  714. X *
  715. X * The order here determines which are suggested first!
  716. X * (together with the imm_cmd class in Rootsymbol above!!;
  717. X *  see ../bed/e1gram.c - initclasses)
  718. X */
  719. X#ifndef GFX
  720. X#define A_SIMPLE_CMD SC1; SC2; SC3
  721. X#else
  722. X#define A_SIMPLE_CMD SC1; SC2; SC3; SC4
  723. X#define SC4 Line; Space; Clear
  724. X#endif
  725. X#define SC1 Share; Quit; Return; Write; Read; Read_raw; Put; Delete
  726. X#define SC2 Report; Fail; Succeed; Insert; Remove; Check; Pass
  727. X#define SC3 Set; Suggestion; KEYWORD; Kw_plus
  728. X
  729. X#define A_CONTROL_CMD If; While; For
  730. X#define A_COMP_CMD Short_comp; Long_comp; Cmt_comp; Select
  731. X#define A_CMD If; For; A_COMP_CMD; A_SIMPLE_CMD; While
  732. X/* #define A_SHORTCMD A_SIMPLE_CMD; Cmt_cmd */
  733. X#define A_SHORTCMD If; For; A_SIMPLE_CMD; While; Short_comp; Cmt_comp; Cmt_cmd
  734. X
  735. Xcmd: COMMENT; A_CMD; Cmt_cmd.
  736. XCmt_cmd: simple_cmd, " ", COMMENT.
  737. Xsimple_cmd: A_SIMPLE_CMD.
  738. XShort_comp: ifforwhile,  "\t", shortcmd, "\b".
  739. Xshortcmd: A_SHORTCMD.
  740. XCmt_comp: ifforwhile, COMMENT.
  741. XLong_comp: c_ifforwhile, "\t", suite, "\b".
  742. Xc_ifforwhile: A_CONTROL_CMD; Cmt_comp.
  743. Xifforwhile: A_CONTROL_CMD.
  744. X
  745. X/* The simple commands are separated in two parts:
  746. X * those that can be "softened" because their first keyword(s) may
  747. X * start a User Defined Command,
  748. X * and those that cannot (Check, If, While, Return, Report, How).
  749. X * this separation is used in ../bed/e1que2.c!!! (hack? HACK!)
  750. X */
  751. XPut: R_PUT, expression, R_IN_put, address.
  752. XInsert: R_INSERT, expression, R_IN_insert, address.
  753. XRemove: R_REMOVE, expression, R_FROM_remove, address.
  754. XDelete: R_DELETE, address.
  755. XShare: R_SHARE, naming.
  756. XWrite: R_WRITE, expression.
  757. XRead: R_READ, address, R_EG, single_expression.
  758. XRead_raw: R_READ, address, R_RAW.
  759. XSet: R_SET_RANDOM, expression.
  760. XPass: R_PASS.
  761. X
  762. X#ifdef GFX
  763. XSpace: R_SPACE, R_TO_space, expression, expression.
  764. XLine: R_LINE, expression, R_TO_line, expression.
  765. XClear: R_CLEAR.
  766. X#endif
  767. X
  768. XFor: R_FOR, naming, R_IN_for, single_expression, ": ".
  769. X
  770. XQuit: R_QUIT.
  771. XSucceed: R_SUCCEED.
  772. XFail: R_FAIL.
  773. X
  774. X/* non-softenable: */
  775. X
  776. XCheck: R_CHECK, test.
  777. XIf: R_IF, test, ": ".
  778. XWhile: R_WHILE, test, ": ".
  779. X
  780. XSelect: R_SELECT, optional_comment, "\t", t_suite,  "\b", optional_comment.
  781. X    /* since SELECT SOMETHING is allowed, but SELECT: ANOTHER is not */
  782. XReturn: R_RETURN, expression.
  783. XReport: R_REPORT, test.
  784. X
  785. X/* for user defined commands: */
  786. XKw_plus: KEYWORD, " ", kw_next.
  787. Xkw_next: Collateral; A_SINGLE_EXPR; KEYWORD; Exp_plus; Kw_plus.
  788. XExp_plus: expression, " ", exp_next.
  789. Xexp_next: KEYWORD; Kw_plus.
  790. X
  791. X/* 
  792. X * Suites
  793. X */
  794. X
  795. Xsuite: Suite.
  796. XSuite: "\n", cmd, optional_suite.
  797. Xoptional_suite: Optional; Suite.
  798. X
  799. Xoptional_cmdsuite: Optional; A_SHORTCMD; Suite.
  800. Xcmdsuite: A_SHORTCMD; Suite.
  801. X
  802. Xt_suite: Test_suite.
  803. XTest_suite: "\n", e_test, ": ", optional_comment, "\t", cmdsuite, "\b",
  804. X    optional_t_suite.
  805. Xoptional_t_suite: Optional; Test_suite.
  806. X
  807. Xoptional_comment: Optional; COMMENT.
  808. X
  809. X/* 
  810. X * Unit
  811. X */
  812. X
  813. X#define A_BODY Head; Cmt_head; Long_unit; Short_unit
  814. X
  815. X/*unit: Optional; A_BODY; Ref_join. ## believed to be unnecessary */
  816. X
  817. XHead: R_HOW_TO, formal_cmd, ": ".
  818. XCmt_head: head, COMMENT.
  819. XLong_unit: commented_head, "\t", suite, "\b".
  820. XShort_unit: head, "\t", shortcmd, "\b".
  821. Xhead: Head.
  822. Xcommented_head: Cmt_head; Head.
  823. X
  824. Xformal_cmd: Formal_return; Formal_report; KEYWORD; Formal_kw_plus.
  825. X
  826. X#define A_SINGLE_NAMING NAME; Compound_naming
  827. XFormal_return: R_RETURN, formal_formula.
  828. XFormal_report: R_REPORT, formal_formula.
  829. X/* the following is too liberal, but that was necessary:
  830. X * the editor allows a formal command with RETURN or REPORT as
  831. X * first keyword, and that cannot be read back without the last
  832. X * alternative in the following rule
  833. X * (another hack? HACK!) */
  834. Xformal_formula: Blocked_ff; Grouped_ff; A_SINGLE_NAMING; Formal_kw_plus.
  835. XBlocked_ff: ff_block, ff_group.
  836. Xff_block: A_SINGLE_NAMING.
  837. Xff_group: Blocked_ff; A_SINGLE_NAMING.
  838. XGrouped_ff: ff_group, " ", formal_formula.
  839. X
  840. XFormal_kw_plus: KEYWORD, " ", formal_kw_next.
  841. Xformal_kw_next: A_NAMING; KEYWORD; Formal_naming_plus; Formal_kw_plus.
  842. XFormal_naming_plus: naming, " ", naming_next.
  843. Xnaming_next: KEYWORD; Formal_kw_plus.
  844. X
  845. XRef_join: refpred, refinements.
  846. Xrefpred: A_BODY.
  847. Xoptional_refinements: Optional; Refinement.
  848. Xrefinements: Refinement.
  849. XRefinement: "\n", name_or_keyword, ": ", optional_comment,
  850. X    "\t", cmdsuite, "\b", optional_refinements.
  851. Xname_or_keyword: NAME; KEYWORD; Keyword_list.
  852. XKeyword_list: KEYWORD, " ", kwltail.
  853. Xkwltail: KEYWORD; Keyword_list.
  854. X
  855. X/*
  856. X * Alternative Roots
  857. X */
  858. X
  859. XUnit_edit: unit_edit.
  860. XTarget_edit: address_edit.
  861. XImm_cmd: imm_cmd.
  862. X
  863. Xunit_edit: Optional; A_BODY; Ref_join.
  864. Xaddress_edit: Optional; A_SINGLE_EXPR.
  865. Ximm_cmd: Optional; COMMENT; Head; A_CMD; Cmt_cmd; Cmt_head;
  866. X    Edit_unit; Edit_address; Workspace_cmd.
  867. X
  868. XEdit_unit: ":", ed_unit.
  869. Xed_unit: Optional; NAME; KEYWORD; Keyword_list; Colon; Sugghowname.
  870. XColon: ":".
  871. XEdit_address: "=", ed_address.
  872. Xed_address: Optional; NAME; Equals.
  873. XEquals: "=".
  874. XWorkspace_cmd: ">", ws_cmd.
  875. Xws_cmd: Optional; NAME; Right.
  876. XRight: ">".
  877. X
  878. XExpression: expression.     /* used by ABC editor for READ EG */
  879. XRaw_input: raw_input.        /* used by ABC editor for READ RAW */
  880. Xraw_input: Optional; RAWINPUT.    /* the underscore prevents clash
  881. X                 * with enveloping Rawinput Symbol 
  882. X                 * (See comments above) */
  883. X/*
  884. X * In addition 'mktable' will generate entries defining
  885. X *    Suggestion: suggestion-body.
  886. X *    Sugghowname: sugghowname-body.
  887. X *    Optional: .
  888. X *    Hole: "?".
  889. X * at the very end of the table containing the Symbol definitions.
  890. X *
  891. X * The first two are only defined if the corresponding lexical items are;
  892. X * suggestion-body denotes the enveloping class for that item;
  893. X * the same for sugghowname-body.
  894. X * (See the comments in read.c).
  895. X */
  896. END_OF_FILE
  897.   if test 13172 -ne `wc -c <'abc/boot/grammar.abc'`; then
  898.     echo shar: \"'abc/boot/grammar.abc'\" unpacked with wrong size!
  899.   fi
  900.   # end of 'abc/boot/grammar.abc'
  901. fi
  902. if test -f 'abc/btr/i1tex.c' -a "${1}" != "-c" ; then 
  903.   echo shar: Will not clobber existing file \"'abc/btr/i1tex.c'\"
  904. else
  905.   echo shar: Extracting \"'abc/btr/i1tex.c'\" \(12939 characters\)
  906.   sed "s/^X//" >'abc/btr/i1tex.c' <<'END_OF_FILE'
  907. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  908. X
  909. X/* B texts */
  910. X
  911. X#include "b.h"
  912. X#include "bmem.h"
  913. X#include "bobj.h"
  914. X#include "i1btr.h"
  915. X#include "i1tlt.h"
  916. X
  917. X#define CURTAIL_TEX    MESS(200, "in t|n, t is not a text")
  918. X#define CURTAIL_NUM    MESS(201, "in t|n, n is not a number")
  919. X#define CURTAIL_INT    MESS(202, "in t|n, n is not an integer")
  920. X#define CURTAIL_BND    MESS(203, "in t|n, n is < 0")
  921. X
  922. X#define BEHEAD_TEX    MESS(204, "in t@n, t is not a text")
  923. X#define BEHEAD_NUM    MESS(205, "in t@n, n is not a number")
  924. X#define BEHEAD_INT    MESS(206, "in t@n, n is not an integer")
  925. X#define BEHEAD_BND    MESS(207, "in t@n, n is > #t + 1")
  926. X
  927. X#define CONCAT_TEX    MESS(208, "in t^u, t or u is not a text")
  928. X#define CONCAT_LONG    MESS(209, "in t^u, the result is too long")
  929. X
  930. X#define REPEAT_TEX    MESS(210, "in t^^n, t is not a text")
  931. X#define REPEAT_NUM    MESS(211, "in t^^n, n is not a number")
  932. X#define REPEAT_INT    MESS(212, "in t^^n, n is not an integer")
  933. X#define REPEAT_NEG    MESS(213, "in t^^n, n is negative")
  934. X#define REPEAT_LONG    MESS(214, "in t^^n, the result is too long")
  935. X
  936. X/*
  937. X * Operations on texts represented as B-trees.
  938. X *
  939. X * Comments:
  940. X * - The functions with 'i' prepended (ibehead, etc.) do no argument
  941. X *   checking at all.  They actually implement the planned behaviour
  942. X *   of | and @, where out-of-bounds numerical values are truncated
  943. X *   rather than causing errors {"abc"|100 = "abc"@-100 = "abc"}.
  944. X * - The 'size' field of all texts must fit in a C int.  If the result of
  945. X *   ^ or ^^ would exceed Maxint in size, a user error is signalled.  If
  946. X *   the size of the *input* value(s) of any operation is Bigsize, a syserr
  947. X *   is signalled.
  948. X * - Argument checking: trims, concat and repeat must check their arguments
  949. X *   for user errors.
  950. X * - t^^n is implemented with an algorithm similar to the 'square and
  951. X *   multiply' algorithm for x**n, using the binary representation of n,
  952. X *   but it uses straightforward 'concat' operations.  A more efficient
  953. X *   scheme is possible [see IW219], but small code seems more important.
  954. X * - Degenerated cases (e.g. t@1, t|0, t^'' or t^^n) are not optimized,
  955. X *   but produce the desired result by virtue of the algorithms used.
  956. X *   The extra checking does not seem worth the overhead for the
  957. X *   non-degenerate cases.
  958. X * - The code for PUT v IN t@h|l is still there, but it is not compiled,
  959. X *   as the interpreter implements the same strategy directly.
  960. X * - Code for outputting texts has been added.    This is called from wri()
  961. X *   to output a text, and has running time O(n), compared to O(n log n)
  962. X *   for the old code in wri().
  963. X *
  964. X * *** WARNING ***
  965. X * - The 'zip' routine and its subroutine 'copynptrs' assume that items and
  966. X *   pointers are stored contiguously, so that &Ptr(p, i+1) == &Ptr(p, i)+1
  967. X *   and &[IB]char(p, i+1) == &[IB]char(p, i)+1.  For pointers, the order
  968. X *   might be reversed in the future; then change the macro Incr(pp, n) below
  969. X *   to *decrement* the pointer!
  970. X * - Mkbtext and bstrval make the same assumption about items (using strncpy
  971. X *   to move charaters to/from a bottom node).
  972. X */
  973. X
  974. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  975. X
  976. X#define IsInner(p) (Flag(p) == Inner)
  977. X#define IsBottom(p) (Flag(p) == Bottom)
  978. X
  979. X#define Incr(pp, n) ((pp) += (n))
  980. X
  981. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  982. X
  983. XVisible char charval(v) value v; {
  984. X    if (!Character(v))
  985. X        syserr(MESS(215, "charval on non-char"));
  986. X    return Bchar(Root(v), 0);
  987. X}
  988. X
  989. XVisible char ncharval(n, v) int n; value v; {
  990. X    value c= thof(n, v);
  991. X    char ch= charval(c);
  992. X    release(c);
  993. X    return ch;
  994. X}
  995. X
  996. XVisible bool character(v) value v; {
  997. X    return Character(v);
  998. X}
  999. X
  1000. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1001. X
  1002. XHidden btreeptr mkbtext(s, len) string s; int len; {
  1003. X    btreeptr p; int chunk, i, n, nbig;
  1004. X
  1005. X    /*
  1006. X     * Determine level of tree.
  1007. X     * This is done for each inner node anew, to avoid having
  1008. X     * to keep an explicit stack.
  1009. X     * Problem is: make sure that for each node at the same
  1010. X     * level, the computation indeed finds the same level!
  1011. X     * (Don't care about efficiency here; in practice the trees
  1012. X     * built by mk_text rarely need more than two levels.)
  1013. X     */
  1014. X    chunk = 0;
  1015. X    i = Maxbottom; /* Next larger chunk size */
  1016. X    while (len > i) {
  1017. X        chunk = i;
  1018. X        i = (i+1) * Maxinner + Maxinner;
  1019. X    }
  1020. X    n = len / (chunk+1); /* Number of items at this level; n+1 subtrees */
  1021. X    chunk = len / (n+1); /* Use minimal chunk size for subtrees */
  1022. X    p = grabbtreenode(chunk ? Inner : Bottom, Ct);
  1023. X    Size(p) = len;
  1024. X    Lim(p) = n;
  1025. X    if (!chunk)
  1026. X        strncpy(&Bchar(p, 0), s, len);
  1027. X    else {
  1028. X        nbig = len+1 - (n+1)*chunk;
  1029. X            /* There will be 'nbig' nodes of size 'chunk'. */
  1030. X            /* The remaining 'n-nbig' will have size 'chunk-1'. */
  1031. X        for (i = 0; i < n; ++i) {
  1032. X            Ptr(p, i) = mkbtext(s, chunk);
  1033. X            s += chunk;
  1034. X            Ichar(p, i) = *s++;
  1035. X            len -= chunk+1;
  1036. X            if (--nbig == 0)
  1037. X                --chunk; /* This was the last 'big' node */
  1038. X        }
  1039. X        Ptr(p, i) = mkbtext(s, len);
  1040. X    }
  1041. X    return p;
  1042. X}
  1043. X
  1044. XVisible value mk_text(s) string s; {
  1045. X    value v; int len = strlen(s);
  1046. X
  1047. X    v = grab(Tex, Ct);
  1048. X    if (len == 0)
  1049. X        Root(v) = Bnil;
  1050. X    else
  1051. X        Root(v) = mkbtext(s, len);
  1052. X    return v;
  1053. X}
  1054. X
  1055. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1056. X
  1057. XHidden string bstrval(buf, p) string buf; btreeptr p; {
  1058. X    /* Returns *next* available position in buffer */
  1059. X    int i, n = Lim(p);
  1060. X    if (IsInner(p)) {
  1061. X        for (i = 0; i < n; ++i) {
  1062. X            buf = bstrval(buf, Ptr(p, i));
  1063. X            *buf++ = Ichar(p, i);
  1064. X        }
  1065. X        return bstrval(buf, Ptr(p, i));
  1066. X    }
  1067. X    strncpy(buf, &Bchar(p, 0), n);
  1068. X    return buf+n;
  1069. X}
  1070. X
  1071. XHidden char *buffer= NULL;
  1072. XVisible string strval(v) value v; {
  1073. X    int len = Tltsize(v);
  1074. X    if (len == Bigsize) syserr(MESS(216, "strval on big text"));
  1075. X    if (len == 0) return "";
  1076. X    if (buffer != NULL)
  1077. X        regetmem(&buffer, (unsigned) len+1);
  1078. X    else
  1079. X        buffer = getmem((unsigned) len+1);
  1080. X    *bstrval(buffer, Root(v)) = '\0';
  1081. X    return buffer;
  1082. X}
  1083. X
  1084. X#ifdef MEMTRACE
  1085. XVisible Procedure endstrval() {     /* hack to free static store */
  1086. X    if (buffer != NULL)
  1087. X        freemem(buffer);
  1088. X}
  1089. X#endif
  1090. X
  1091. XVisible string sstrval(v) value v; {
  1092. X    return (string) savestr(strval(v));
  1093. X}
  1094. X
  1095. XVisible Procedure fstrval(s) string s; {
  1096. X    freestr(s);
  1097. X}
  1098. X
  1099. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1100. X
  1101. Xtypedef struct stackelem {
  1102. X    btreeptr s_ptr;
  1103. X    int s_lim;
  1104. X} stackelem;
  1105. X
  1106. Xtypedef stackelem stack[Maxheight];
  1107. Xtypedef stackelem *stackptr;
  1108. X
  1109. X#define Snil ((stackptr)0)
  1110. X
  1111. X#define Push(s, p, l) ((s)->s_ptr = (p), ((s)->s_lim = (l)), (s)++)
  1112. X#define Pop(s, p, l) (--(s), (p) = (s)->s_ptr, (l) = (s)->s_lim)
  1113. X
  1114. Xextern stackptr unzip();
  1115. Xextern Procedure cpynptrs();
  1116. Xextern int movnptrs();
  1117. X
  1118. XHidden btreeptr zip(s1, sp1, s2, sp2) stackptr s1, sp1, s2, sp2; {
  1119. X    btreeptr p1, p2, newptr[2]; int l1, l2, i, n, n2;
  1120. X#define q1 newptr[0]
  1121. X#define q2 newptr[1]
  1122. X    char newitem; bool overflow, underflow, inner;
  1123. X    char *cp; btreeptr *pp;
  1124. X    char cbuf[2*Maxbottom]; btreeptr pbuf[2*Maxinner+2];
  1125. X
  1126. X    while (s1 < sp1 && s1->s_lim == 0)
  1127. X        ++s1;
  1128. X    while (s2 < sp2 && s2->s_lim == Lim(s2->s_ptr))
  1129. X        ++s2;
  1130. X    inner = overflow = underflow = No;
  1131. X    q1 = Bnil;
  1132. X    while (s1 < sp1 || s2 < sp2) {
  1133. X        if (s1 < sp1)
  1134. X            Pop(sp1, p1, l1);
  1135. X        else
  1136. X            p1 = Bnil;
  1137. X        if (s2 < sp2)
  1138. X            Pop(sp2, p2, l2);
  1139. X        else
  1140. X            p2 = Bnil;
  1141. X        cp = cbuf;
  1142. X        if (p1 != Bnil) {
  1143. X            strncpy(cp, (inner ? &Ichar(p1, 0) : &Bchar(p1, 0)), l1);
  1144. X            cp += l1;
  1145. X        }
  1146. X        if (overflow)
  1147. X            *cp++ = newitem;
  1148. X        n = cp - cbuf;
  1149. X        if (p2 != Bnil) {
  1150. X            strncpy(cp, (inner ? &Ichar(p2, l2) : &Bchar(p2, l2)), Lim(p2)-l2);
  1151. X            n += Lim(p2)-l2;
  1152. X        }
  1153. X        if (inner) {
  1154. X            pp = pbuf; /***** Change if reverse direction! *****/
  1155. X            if (p1 != Bnil) {
  1156. X                cpynptrs(pp, &Ptr(p1, 0), l1);
  1157. X                Incr(pp, l1);
  1158. X            }
  1159. X            movnptrs(pp, newptr, 1+overflow);
  1160. X            Incr(pp, 1+overflow);
  1161. X            if (p2 != Bnil) {
  1162. X                cpynptrs(pp, &Ptr(p2, l2+1), Lim(p2)-l2);
  1163. X                Incr(pp, Lim(p2)-l2);
  1164. X            }
  1165. X            if (underflow) {
  1166. X                underflow= No;
  1167. X                n= uflow(n, p1 ? l1 : 0, cbuf, pbuf, Ct);
  1168. X            }
  1169. X        }
  1170. X        overflow = No;
  1171. X        if (n > (inner ? Maxinner : Maxbottom)) {
  1172. X            overflow = Yes;
  1173. X            n2 = (n-1)/2;
  1174. X            n -= n2+1;
  1175. X        }
  1176. X        else if (n < (inner ? Mininner : Minbottom))
  1177. X            underflow = Yes;
  1178. X        q1 = grabbtreenode(inner ? Inner : Bottom, Ct);
  1179. X        Lim(q1) = n;
  1180. X        cp = cbuf;
  1181. X        strncpy((inner ? &Ichar(q1, 0) : &Bchar(q1, 0)), cp, n);
  1182. X        cp += n;
  1183. X        if (inner) {
  1184. X            pp = pbuf;
  1185. X            i = movnptrs(&Ptr(q1, 0), pp, n+1);
  1186. X            Incr(pp, n+1);
  1187. X            n += i;
  1188. X        }
  1189. X        Size(q1) = n;
  1190. X        if (overflow) {
  1191. X            newitem = *cp++;
  1192. X            q2 = grabbtreenode(inner ? Inner : Bottom, Ct);
  1193. X            Lim(q2) = n2;
  1194. X            strncpy((inner ? &Ichar(q2, 0) : &Bchar(q2, 0)), cp, n2);
  1195. X            if (inner)
  1196. X                n2 += movnptrs(&Ptr(q2, 0), pp, n2+1);
  1197. X            Size(q2) = n2;
  1198. X        }
  1199. X        inner = Yes;
  1200. X    }
  1201. X    if (overflow)
  1202. X        q1 = mknewroot(q1, (itemptr)&newitem, q2, Ct);
  1203. X    return q1;
  1204. X#undef q1
  1205. X#undef q2
  1206. X}
  1207. X
  1208. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1209. X
  1210. XHidden value ibehead(v, h) value v; int h; { /* v@h */
  1211. X    stack s; stackptr sp;
  1212. X    sp = (stackptr) unzip(Root(v), h-1, s);
  1213. X    v = grab(Tex, Ct);
  1214. X    Root(v) = zip(Snil, Snil, s, sp);
  1215. X    return v;
  1216. X}
  1217. X
  1218. XHidden value icurtail(v, t) value v; int t; { /* v|t */
  1219. X    stack s; stackptr sp;
  1220. X    sp = (stackptr) unzip(Root(v), t, s);
  1221. X    v = grab(Tex, Ct);
  1222. X    Root(v) = zip(s, sp, Snil, Snil);
  1223. X    return v;
  1224. X}
  1225. X
  1226. XHidden value iconcat(v, w) value v, w; { /* v^w */
  1227. X    stack s1, s2;
  1228. X    stackptr sp1 = (stackptr) unzip(Root(v), Tltsize(v), s1);
  1229. X    stackptr sp2 = (stackptr) unzip(Root(w), 0, s2);
  1230. X    v = grab(Tex, Ct);
  1231. X    Root(v) = zip(s1, sp1, s2, sp2);
  1232. X    return v;
  1233. X}
  1234. X
  1235. X#define Odd(n) (((n)&1) != 0)
  1236. X
  1237. XHidden value irepeat(v, n) value v; int n; { /* v^^n */
  1238. X    value x, w = grab(Tex, Ct);
  1239. X    Root(w) = Bnil;
  1240. X    v = copy(v);
  1241. X    while (n > 0) {
  1242. X        if (Odd(n)) {
  1243. X            w = iconcat(x = w, v);
  1244. X            release(x);
  1245. X        }
  1246. X        n /= 2;
  1247. X        if (n == 0)
  1248. X            break;
  1249. X        v = iconcat(x = v, v);
  1250. X        release(x);
  1251. X    }
  1252. X    release(v);
  1253. X    return w;
  1254. X}
  1255. X
  1256. X#ifdef UNUSED_CODE
  1257. XHidden value jrepeat(v, n) value v; int n; { /* v^^n, recursive solution */
  1258. X    value w, x;
  1259. X    if (n <= 1) {
  1260. X        if (n == 1)
  1261. X            return copy(v);
  1262. X        w = grab(Tex, Ct);
  1263. X        Root(w) = Bnil;
  1264. X        return w;
  1265. X    }
  1266. X    w = jrepeat(v, n/2);
  1267. X    w = iconcat(x = w, w);
  1268. X    release(x);
  1269. X    if (Odd(n)) {
  1270. X        w = iconcat(x = w, v);
  1271. X        release(x);
  1272. X    }
  1273. X    return w;
  1274. X}
  1275. X#endif /* UNUSED_CODE */
  1276. X
  1277. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1278. X
  1279. XVisible value curtail(t, after) value t, after; {
  1280. X    int syzcurv, syztext;
  1281. X
  1282. X    if (!Is_text(t)) {
  1283. X        reqerr(CURTAIL_TEX);
  1284. X        return Vnil;
  1285. X    }
  1286. X    if (!Is_number(after)) {
  1287. X        reqerr(CURTAIL_NUM);
  1288. X        return Vnil;
  1289. X    }
  1290. X    syztext = Tltsize(t);
  1291. X    if (syztext == Bigsize)
  1292. X        syserr(MESS(217, "curtail on very big text"));
  1293. X     if (large(after) || (syzcurv = intval(after)) < 0) {
  1294. X        reqerr(CURTAIL_BND);
  1295. X        return Vnil;
  1296. X    }
  1297. X    return icurtail(t, syzcurv);
  1298. X}
  1299. X
  1300. XVisible value behead(t, before) value t, before; {
  1301. X    int syzbehv, syztext;
  1302. X
  1303. X    if (!Is_text(t)) {
  1304. X        reqerr(BEHEAD_TEX);
  1305. X        return Vnil;
  1306. X    }
  1307. X    if (!Is_number(before)) {
  1308. X        reqerr(BEHEAD_NUM);
  1309. X        return Vnil;
  1310. X    }
  1311. X    syztext = Tltsize(t);
  1312. X    if (syztext == Bigsize) syserr(MESS(218, "behead on very big text"));
  1313. X    if (large(before) || (syzbehv = intval(before)) > syztext + 1) {
  1314. X        reqerr(BEHEAD_BND);
  1315. X        return Vnil;
  1316. X    }
  1317. X    return ibehead(t, syzbehv);
  1318. X}
  1319. X
  1320. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1321. X
  1322. XVisible value concat(tleft, tright) value tleft, tright; {
  1323. X    int syzleft, syzright;
  1324. X    if (!Is_text(tleft) || !Is_text(tright)) {
  1325. X        reqerr(CONCAT_TEX);
  1326. X        return Vnil;
  1327. X    }
  1328. X    syzleft = Tltsize(tleft);
  1329. X    syzright =  Tltsize(tright);
  1330. X    if (syzleft == Bigsize || syzright == Bigsize)
  1331. X        syserr(MESS(219, "concat on very big text"));
  1332. X    if (syzleft > Maxint-syzright
  1333. X        || syzright > Maxint-syzleft) {
  1334. X        reqerr(CONCAT_LONG);
  1335. X        return Vnil;
  1336. X    }
  1337. X    return iconcat(tleft, tright);
  1338. X}
  1339. X
  1340. XVisible Procedure concato(v, t) value* v; value t; {
  1341. X    value v1= *v;
  1342. X    *v= concat(*v, t);
  1343. X    release(v1);
  1344. X}
  1345. X
  1346. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1347. X
  1348. XVisible value repeat(t, n) value t, n; {
  1349. X    int tsize, k;
  1350. X
  1351. X    if (!Is_text(t)) {
  1352. X        reqerr(REPEAT_TEX);
  1353. X        return Vnil;
  1354. X    }
  1355. X    if (!Is_number(n)) {
  1356. X        reqerr(REPEAT_NUM);
  1357. X        return Vnil;
  1358. X    }
  1359. X    if (numcomp(n, zero) < 0) {
  1360. X        reqerr(REPEAT_NEG);
  1361. X        return Vnil;
  1362. X    }
  1363. X    tsize = Tltsize(t);
  1364. X    if (tsize == 0) return copy(t);
  1365. X
  1366. X    if (large(n) || Maxint/tsize < (k = intval(n))) {
  1367. X        reqerr(REPEAT_LONG);
  1368. X        return Vnil;
  1369. X    }
  1370. X    return irepeat(t, k);
  1371. X}
  1372. X
  1373. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  1374. X
  1375. XVisible Procedure wrtext(putch, v, quote) int (*putch)(); value v; char quote; {
  1376. X    if (v == Vnil || !Is_text(v)) {
  1377. X        (*putch)('?');
  1378. X        return;
  1379. X    }
  1380. X    if (quote) (*putch)(quote);
  1381. X    if (Root(v) != Bnil) wrbtext(putch, Root(v), quote);
  1382. X    if (quote) (*putch)(quote);
  1383. X}
  1384. X
  1385. XHidden Procedure wrbtext(putch, p, quote)
  1386. X int (*putch)(); btreeptr p; char quote; {
  1387. X    int i, n = Lim(p); char c;
  1388. X    if (IsInner(p)) {
  1389. X        for (i = 0; still_ok && i < n; ++i) {
  1390. X            wrbtext(putch, Ptr(p, i), quote);
  1391. X            c = Ichar(p, i);
  1392. X            (*putch)(c);
  1393. X            if (quote && (c == quote || c == '`')) (*putch)(c);
  1394. X        }
  1395. X        wrbtext(putch, Ptr(p, i), quote);
  1396. X    }
  1397. X    else if (quote) {
  1398. X        for (i = 0; i < n; ++i) {
  1399. X            c = Bchar(p, i);
  1400. X            (*putch)(c);
  1401. X            if (c == quote || c == '`') (*putch)(c);
  1402. X        }
  1403. X    }
  1404. X    else {
  1405. X        for (i = 0; i < n; ++i) (*putch)(Bchar(p, i));
  1406. X    }
  1407. X}
  1408. X
  1409. END_OF_FILE
  1410.   if test 12939 -ne `wc -c <'abc/btr/i1tex.c'`; then
  1411.     echo shar: \"'abc/btr/i1tex.c'\" unpacked with wrong size!
  1412.   fi
  1413.   # end of 'abc/btr/i1tex.c'
  1414. fi
  1415. if test -f 'abc/lin/i1tlt.c' -a "${1}" != "-c" ; then 
  1416.   echo shar: Will not clobber existing file \"'abc/lin/i1tlt.c'\"
  1417. else
  1418.   echo shar: Extracting \"'abc/lin/i1tlt.c'\" \(11273 characters\)
  1419.   sed "s/^X//" >'abc/lin/i1tlt.c' <<'END_OF_FILE'
  1420. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1421. X
  1422. X/* generic routines for B texts, lists and tables */
  1423. X
  1424. X#include "b.h"
  1425. X#include "bint.h"
  1426. X#include "feat.h"
  1427. X#include "bobj.h"
  1428. X#include "i1tlt.h"
  1429. X
  1430. X#define SIZE_TLT    MESS(300, "in #t, t is not a text list or table")
  1431. X
  1432. X#define SIZE2_TLT    MESS(301, "in e#t, t is not a text list or table")
  1433. X#define SIZE2_CHAR    MESS(302, "in e#t, t is a text, but e is not a character")
  1434. X
  1435. X#define MIN_TLT        MESS(303, "in min t, t is not a text list or table")
  1436. X#define MIN_EMPTY    MESS(304, "in min t, t is empty")
  1437. X
  1438. X#define MAX_TLT        MESS(305, "in max t, t is not a text list or table")
  1439. X#define MAX_EMPTY    MESS(306, "in max t, t is empty")
  1440. X
  1441. X#define MIN2_TLT    MESS(307, "in e min t, t is not a text list or table")
  1442. X#define MIN2_EMPTY    MESS(308, "in e min t, t is empty")
  1443. X#define MIN2_CHAR    MESS(309, "in e min t, t is a text, but e is not a character")
  1444. X#define MIN2_ELEM    MESS(310, "in e min t, no element of t exceeds e")
  1445. X
  1446. X#define MAX2_TLT    MESS(311, "in e max t, t is not a text list or table")
  1447. X#define MAX2_EMPTY    MESS(312, "in e max t, t is empty")
  1448. X#define MAX2_CHAR    MESS(313, "in e max t, t is a text, but e is not a character")
  1449. X#define MAX2_ELEM    MESS(314, "in e max t, no element of t is less than e")
  1450. X
  1451. X#define ITEM_TLT    MESS(315, "in t item n, t is not a text list or table")
  1452. X#define ITEM_EMPTY    MESS(316, "in t item n, t is empty")
  1453. X#define ITEM_NUM    MESS(317, "in t item n, n is not a number")
  1454. X#define ITEM_INT    MESS(318, "in t item n, n is not an integer")
  1455. X#define ITEM_L_BND    MESS(319, "in t item n, n is < 1")
  1456. X#define ITEM_U_BND    MESS(320, "in t item n, n exceeds #t")
  1457. X
  1458. X#ifdef B_COMPAT
  1459. X
  1460. X#define THOF_TLT    MESS(321, "in n th'of t, t is not a text list or table")
  1461. X#define THOF_EMPTY    MESS(322, "in n th'of t, t is empty")
  1462. X#define THOF_NUM    MESS(323, "in n th'of t, n is not a number")
  1463. X#define THOF_INT    MESS(324, "in n th'of t, n is not an integer")
  1464. X#define THOF_L_BND    MESS(325, "in n th'of t, n is < 1")
  1465. X#define THOF_U_BND    MESS(326, "in n th'of t, n exceeds #t")
  1466. X
  1467. X#endif /* B_COMPAT */
  1468. X
  1469. Xextern bool comp_ok;
  1470. X
  1471. XVisible value mk_elt() { return grab(ELT, 0); }
  1472. X
  1473. XVisible value size(x) value x; { /* monadic # operator */
  1474. X    intlet n= 0;
  1475. X    if (Is_range(x))
  1476. X        return rangesize(Lwb(x), Upb(x));
  1477. X    else if (!Is_tlt(x)) 
  1478. X        interr(SIZE_TLT);
  1479. X    else
  1480. X        n= Length(x);
  1481. X    return mk_integer((int) n);
  1482. X}
  1483. X
  1484. X#define Lisent(tp,k) (*(tp+(k)))
  1485. X
  1486. XVisible value size2(v, t) value v, t; { /* Dyadic # operator */
  1487. X    intlet len, n= 0, k; value *tp= Ats(t);
  1488. X    if (!Is_tlt(t)) {
  1489. X        interr(SIZE2_TLT);
  1490. X        return mk_integer((int) n);
  1491. X    }
  1492. X    len= Length(t);
  1493. X    switch (Type(t)) {
  1494. X    case Tex:
  1495. X        {string cp= (string)tp; char c;
  1496. X            if (Type(v) != Tex || Length(v) != 1)
  1497. X                interr(SIZE2_CHAR);
  1498. X            else {
  1499. X                c= *Str(v);
  1500. X                for (k= 0; k < len; k++) if (*cp++ == c) n++;
  1501. X            }
  1502. X        } break;
  1503. X    case ELT:
  1504. X        break;
  1505. X    case Lis:
  1506. X        {intlet lo= -1, mi, xx, mm, hi= len; relation c;
  1507. X        bins:    if (hi-lo < 2) break;
  1508. X            mi= (lo+hi)/2;
  1509. X            if ((c= compare(v, Lisent(tp,mi))) == 0) goto some;
  1510. X            if (!comp_ok) break;
  1511. X            if (c < 0) hi= mi; else lo= mi;
  1512. X            goto bins;
  1513. X        some:    xx= mi;
  1514. X            while (xx-lo > 1) {
  1515. X                mm= (lo+xx)/2;
  1516. X                if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
  1517. X                else lo= mm;
  1518. X            }
  1519. X            xx= mi;
  1520. X            while (hi-xx > 1) {
  1521. X                mm= (xx+hi)/2;
  1522. X                if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
  1523. X                else hi= mm;
  1524. X            }
  1525. X            n= hi-lo-1;
  1526. X        } break;
  1527. X    case Ran:
  1528. X        if (compare(Lwb(t), v) <= 0
  1529. X            &&
  1530. X            comp_ok
  1531. X            &&
  1532. X            compare(v, Upb(t)) <= 0
  1533. X        )
  1534. X            n= 1;
  1535. X        else
  1536. X            n= 0;
  1537. X        break;
  1538. X    case Tab:
  1539. X        for (k= 0; k < len; k++) {
  1540. X            if (compare(v, Dts(*tp++)) == 0) n++;
  1541. X            if (!comp_ok) { n= 0; break; }
  1542. X        }
  1543. X        break;
  1544. X    default:
  1545. X        syserr(MESS(327, "size2() on non tlt value"));
  1546. X        break;
  1547. X    }
  1548. X    return mk_integer((int) n);
  1549. X}
  1550. X
  1551. XHidden bool less(r) relation r;    { return r<0; }
  1552. XHidden bool greater(r) relation r; { return r>0; }
  1553. X
  1554. XHidden value mm1(t, rel) value t; bool (*rel)(); {
  1555. X    intlet len= Length(t), k; value m, *tp= Ats(t);
  1556. X    switch (Type(t)) {
  1557. X    case Tex:
  1558. X        {string cp= (string) tp; char mc= '\0', mm[2];
  1559. X            for (k= 0; k < len; k++) {
  1560. X                if (mc == '\0' || ((*rel)(*cp < mc ? -1 : (*cp > mc ? 1 : 0))))
  1561. X                    mc= *cp;
  1562. X                cp++;
  1563. X            }
  1564. X            mm[0]= mc; mm[1]= '\0';
  1565. X            m= mk_text(mm);
  1566. X        } break;
  1567. X    case Lis:
  1568. X        if ((*rel)(-1)) /*min*/ m= copy(*Ats(t));
  1569. X        else m= copy(*(Ats(t)+len-1));
  1570. X        break;
  1571. X    case Ran:
  1572. X        if ((*rel)(-1)) /*min*/ m= copy(Lwb(t));
  1573. X        else m= copy(Upb(t));
  1574. X        break;
  1575. X    case Tab:
  1576. X        {value dm= Vnil;
  1577. X            for (k= 0; k < len; k++) {
  1578. X                if (dm == Vnil)
  1579. X                    dm= Dts(*tp);
  1580. X                else {
  1581. X                    relation c= compare(Dts(*tp), dm);
  1582. X                    if (!comp_ok) 
  1583. X                        return Vnil;
  1584. X                    if ((*rel)(c))
  1585. X                        dm= Dts(*tp);
  1586. X                }
  1587. X                tp++;
  1588. X            }
  1589. X            m= copy(dm);
  1590. X        } break;
  1591. X    default:
  1592. X        syserr(MESS(328, "mm1() on non tlt value"));
  1593. X    }
  1594. X    return m;
  1595. X}
  1596. X
  1597. XHidden value mm2(v, t, rel) value v, t; bool (*rel)(); {
  1598. X    intlet len= Length(t), k; value m= Vnil, *tp= Ats(t);
  1599. X    switch (Type(t)) {
  1600. X    case Tex:
  1601. X        {string cp= (string) tp; char c, mc= '\0', mm[2];
  1602. X            c= *Str(v);
  1603. X            for (k= 0; k < len; k++) {
  1604. X                if ((*rel)(c < *cp ? -1 : c > *cp ? 1 : 0)) {
  1605. X                    if (mc == '\0' || (*rel)(*cp < mc ? -1 : *cp>mc ? 1 : 0))
  1606. X                        mc= *cp;
  1607. X                }
  1608. X                cp++;
  1609. X            }
  1610. X            if (mc != '\0') {
  1611. X                mm[0]= mc; mm[1]= '\0';
  1612. X                m= mk_text(mm);
  1613. X            }
  1614. X        } break;
  1615. X    case Lis:
  1616. X        {intlet lim1, mid, lim2; relation c;
  1617. X            if ((*rel)(-1)) { /*min*/
  1618. X                lim1= 0; lim2= len-1;
  1619. X            } else {
  1620. X                lim2= 0; lim1= len-1;
  1621. X            }
  1622. X            c= compare(v, Lisent(tp, lim2));
  1623. X            if (!comp_ok) return Vnil;
  1624. X            if (!(*rel)(c)) break;
  1625. X            if (len == 1 || (*rel)(compare(v, Lisent(tp,lim1)))) {
  1626. X                m= copy(Lisent(tp,lim1));
  1627. X                break;
  1628. X            }
  1629. X            /* v rel tp[lim2] && !(v rel tp[lim1]) */
  1630. X            while (abs(lim2-lim1) > 1) {
  1631. X                mid= (lim1+lim2)/2;
  1632. X                if ((*rel)(compare(v, Lisent(tp,mid)))) lim2= mid;
  1633. X                else lim1= mid;
  1634. X            }
  1635. X            m= copy(Lisent(tp,lim2));
  1636. X        } break;
  1637. X    case Ran:
  1638. X        {relation c= compare(v, Lwb(t));
  1639. X            if (!comp_ok)
  1640. X                return Vnil;
  1641. X            if ((*rel)(-1)) {
  1642. X                /* min2 */
  1643. X                if (c < 0)
  1644. X                    m= copy(Lwb(t));
  1645. X                else if (compare(v, Upb(t)) < 0) {
  1646. X                    if (integral(v))
  1647. X                        m= sum(v, one);
  1648. X                    else
  1649. X                        m= ceilf(v);
  1650. X                }
  1651. X                else
  1652. X                    m= Vnil;
  1653. X            }
  1654. X            else {
  1655. X                /* max2 */
  1656. X                if (c <= 0)
  1657. X                    m= Vnil;
  1658. X                else if (compare(v, Upb(t)) <= 0) {
  1659. X                    if (integral(v))
  1660. X                        m= diff(v, one);
  1661. X                    else
  1662. X                        m= floorf(v);
  1663. X                }
  1664. X                else
  1665. X                    m= copy(Upb(t));
  1666. X            }
  1667. X        } break;
  1668. X    case Tab:
  1669. X        {value dm= Vnil; relation c;
  1670. X            for (k= 0; k < len; k++) {
  1671. X                c= compare(v, Dts(*tp));
  1672. X                if (!comp_ok) return Vnil;
  1673. X                if ((*rel)(c)) {
  1674. X                    if (dm == Vnil ||
  1675. X                        (*rel)(compare(Dts(*tp), dm)))
  1676. X                        dm= Dts(*tp);
  1677. X                }
  1678. X                tp++;
  1679. X            }
  1680. X            if (dm != Vnil) m= copy(dm);
  1681. X        } break;
  1682. X    default:
  1683. X        syserr(MESS(329, "mm2() on non tlt value"));
  1684. X        break;
  1685. X    }
  1686. X    return m;
  1687. X}
  1688. X
  1689. XVisible value min1(t) value t; { /* Monadic min */
  1690. X    value m= Vnil;
  1691. X    if (!Is_tlt(t))
  1692. X        interr(MIN_TLT);
  1693. X    else if (Length(t) == 0)
  1694. X        interr(MIN_EMPTY);
  1695. X    else m= mm1(t, less);
  1696. X    return m;
  1697. X}
  1698. X
  1699. XVisible value min2(v, t) value v, t; {
  1700. X    value m= Vnil;
  1701. X    if (!Is_tlt(t))
  1702. X        interr(MIN2_TLT);
  1703. X    else if (Length(t) == 0)
  1704. X        interr(MIN2_EMPTY);
  1705. X    else if (Is_text(t)) {
  1706. X        if (!Is_text(v) || Length(v) != 1)
  1707. X            interr(MIN2_CHAR);
  1708. X    }
  1709. X    if (still_ok) {
  1710. X        m= mm2(v, t, less);
  1711. X        if (m == Vnil && still_ok)
  1712. X            interr(MIN2_ELEM);
  1713. X    }
  1714. X    return m;
  1715. X}
  1716. X
  1717. XVisible value max1(t) value t; {
  1718. X    value m= Vnil;
  1719. X    if (!Is_tlt(t))
  1720. X        interr(MAX_TLT);
  1721. X    else if (Length(t) == 0)
  1722. X        interr(MAX_EMPTY);
  1723. X    else m= mm1(t, greater);
  1724. X    return m;
  1725. X}
  1726. X
  1727. XVisible value max2(v, t) value v, t; {
  1728. X    value m= Vnil;
  1729. X    if (!Is_tlt(t))
  1730. X        interr(MAX2_TLT);
  1731. X    else if (Length(t) == 0)
  1732. X        interr(MAX2_EMPTY);
  1733. X    else if (Is_text(t)) {
  1734. X        if (!Is_text(v) || Length(v) != 1)
  1735. X            interr(MAX2_CHAR);
  1736. X    }
  1737. X    if (still_ok) {
  1738. X        m= mm2(v, t, greater);
  1739. X        if (m == Vnil && still_ok)
  1740. X            interr(MAX2_ELEM);
  1741. X    }
  1742. X    return m;
  1743. X}
  1744. X
  1745. XVisible value item(t, n) value t, n; {
  1746. X    value w= Vnil;
  1747. X    int m;
  1748. X    if (!Is_tlt(t))
  1749. X        interr(ITEM_TLT);
  1750. X    else if (!Is_number(n) || !integral(n))
  1751. X        interr(ITEM_INT);
  1752. X    else if (empty(t))
  1753. X        interr(ITEM_EMPTY);
  1754. X    else if (Is_range(t)) {
  1755. X        value r;
  1756. X        r= rangesize(Lwb(t), Upb(t));
  1757. X        if (compare(n, zero) <= 0)
  1758. X            interr(ITEM_L_BND);
  1759. X        else if (compare(r, n) < 0)
  1760. X            interr(ITEM_U_BND);
  1761. X        else {
  1762. X            release(r);
  1763. X            r= sum(n, Lwb(t));
  1764. X            w= diff(r, one);
  1765. X        }
  1766. X        release(r);
  1767. X    }
  1768. X    else {
  1769. X        m= intval(n);
  1770. X        if (m <= 0)
  1771. X            interr(ITEM_L_BND);
  1772. X        else if (m > Length(t))
  1773. X            interr(ITEM_U_BND);
  1774. X        else w= thof(m, t);
  1775. X    } 
  1776. X    return w;
  1777. X}
  1778. X
  1779. X#ifdef B_COMPAT
  1780. X
  1781. XVisible value th_of(n, t) value n, t; {
  1782. X    value w= Vnil;
  1783. X    int m;
  1784. X    if (!Is_tlt(t))
  1785. X        interr(THOF_TLT);
  1786. X    else if (!Is_number(n) || !integral(n))
  1787. X        interr(THOF_INT);
  1788. X    else if (empty(t))
  1789. X        interr(THOF_EMPTY);
  1790. X    else if (Is_range(t)) {
  1791. X        value r;
  1792. X        r= rangesize(Lwb(t), Upb(t));
  1793. X        if (compare(n, zero) <= 0)
  1794. X            interr(THOF_L_BND);
  1795. X        else if (compare(r, n) < 0)
  1796. X            interr(THOF_U_BND);
  1797. X        else {
  1798. X            release(r);
  1799. X            r= sum(n, Lwb(t));
  1800. X            w= diff(r, one);
  1801. X        }
  1802. X        release(r);
  1803. X    }
  1804. X    else {
  1805. X        m= intval(n);
  1806. X        if (m <= 0)
  1807. X            interr(THOF_L_BND);
  1808. X        else if (m > Length(t))
  1809. X            interr(THOF_U_BND);
  1810. X        else w= thof(m, t);
  1811. X    } 
  1812. X    return w;
  1813. X}
  1814. X
  1815. X#endif /* B_COMPAT */
  1816. X
  1817. XVisible value thof(n, t) int n; value t; {
  1818. X    value w= Vnil; value r;
  1819. X    switch (Type(t)) {
  1820. X        case Tex:
  1821. X            {char ww[2];
  1822. X                ww[0]= *(Str(t)+n-1); ww[1]= '\0';
  1823. X                w= mk_text(ww);
  1824. X            } break;
  1825. X        case Lis:
  1826. X            w= copy(*(Ats(t)+n-1));
  1827. X            break;
  1828. X        case Ran:
  1829. X            r= sum(w= mk_integer(n), Lwb(t));
  1830. X            release(w);
  1831. X            w= diff(r, one);
  1832. X            release(r);
  1833. X            break;
  1834. X        case Tab:
  1835. X            w= copy(Dts(*(Ats(t)+n-1)));
  1836. X            break;
  1837. X        default:
  1838. X            syserr(MESS(330, "thof() on non tlt value"));
  1839. X            break;
  1840. X    }
  1841. X    return w;
  1842. X}
  1843. X
  1844. XVisible bool found_ok= Yes;
  1845. X
  1846. XVisible bool found(elem, v, probe, where)
  1847. X    value (*elem)(), v, probe; intlet *where;
  1848. X    /* think of elem(v,lo-1) as -Infinity and elem(v,hi+1) as +Infinity.
  1849. X       found and where at the end satisfy:
  1850. X       SELECT:
  1851. X           SOME k IN {lo..hi} HAS probe = elem(v,k):
  1852. X           found = Yes AND where = k
  1853. X           ELSE: found = No AND elem(v,where-1) < probe < elem(v,where).
  1854. X    */
  1855. X{relation c; intlet lo=0, hi= Length(v)-1;
  1856. X    found_ok= Yes;
  1857. X    if (lo > hi) { *where= lo; return No; }
  1858. X    if ((c= compare(probe, (*elem)(v, lo))) == 0) {*where= lo; return Yes; }
  1859. X    if (!comp_ok || c < 0) { found_ok= comp_ok; *where=lo; return No; }
  1860. X    if (lo == hi) { *where=hi+1; return No; }
  1861. X    if ((c= compare(probe, (*elem)(v, hi))) == 0) { *where=hi; return Yes; }
  1862. X    if (!comp_ok || c > 0) { found_ok= comp_ok; *where=hi+1; return No; }
  1863. X    /* elem(lo) < probe < elem(hi) */
  1864. X    while (hi-lo > 1) {
  1865. X        if ((c= compare(probe, (*elem)(v, (lo+hi)/2))) == 0) {
  1866. X            *where= (lo+hi)/2; return Yes;
  1867. X        }
  1868. X        if (!comp_ok) { found_ok= comp_ok; *where= lo; return No; }
  1869. X        if (c < 0) hi= (lo+hi)/2; else lo= (lo+hi)/2;
  1870. X    }
  1871. X    *where= hi; return No;
  1872. X}
  1873. X
  1874. XVisible bool in(v, t) value v, t; {
  1875. X    intlet where, k, len; value *tp= Ats(t);
  1876. X    switch (Type(t)) {
  1877. X    case Tex:
  1878. X        return strchr((string) tp, *Str(v)) != 0;
  1879. X    case ELT:
  1880. X        return No;
  1881. X    case Lis:
  1882. X        return found(list_elem, t, v, &where);
  1883. X    case Ran:
  1884. X        return (integral(v)
  1885. X            &&
  1886. X            compare(Lwb(t), v) <= 0
  1887. X            &&
  1888. X            compare(v, Upb(t)) <= 0);
  1889. X    case Tab:
  1890. X        len= Length(t);
  1891. X        for (k= 0; k < len; k++) {
  1892. X            if (compare(v, Dts(*tp++)) == 0) return Yes;
  1893. X            if (!comp_ok) return No;
  1894. X        }
  1895. X        return No;
  1896. X    default:
  1897. X        syserr(MESS(331, "in() on non tlt value"));
  1898. X        return No;
  1899. X    }
  1900. X}
  1901. X
  1902. XVisible bool empty(v) value v; {
  1903. X    switch (Type(v)) {
  1904. X    case Tex:
  1905. X    case Lis:
  1906. X    case Ran:
  1907. X    case Tab:
  1908. X    case ELT:
  1909. X        return (Length(v) == 0);
  1910. X    default:
  1911. X        syserr(MESS(332, "empty() on non tlt value"));
  1912. X        return (No);
  1913. X    }
  1914. X}
  1915. END_OF_FILE
  1916.   if test 11273 -ne `wc -c <'abc/lin/i1tlt.c'`; then
  1917.     echo shar: \"'abc/lin/i1tlt.c'\" unpacked with wrong size!
  1918.   fi
  1919.   # end of 'abc/lin/i1tlt.c'
  1920. fi
  1921. echo shar: End of archive 12 \(of 25\).
  1922. cp /dev/null ark12isdone
  1923. MISSING=""
  1924. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
  1925.     if test ! -f ark${I}isdone ; then
  1926.     MISSING="${MISSING} ${I}"
  1927.     fi
  1928. done
  1929. if test "${MISSING}" = "" ; then
  1930.     echo You have unpacked all 25 archives.
  1931.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1932. else
  1933.     echo You still must unpack the following archives:
  1934.     echo "        " ${MISSING}
  1935. fi
  1936. exit 0 # Just in case...
  1937.