home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / sources / games / 313 < prev    next >
Encoding:
Internet Message Format  |  1993-01-28  |  58.5 KB

  1. Path: sparky!uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i005:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part05/108
  5. Message-ID: <4288@master.CNA.TEK.COM>
  6. Date: 28 Jan 93 19:10:52 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1859
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  12. Posting-number: Volume 16, Issue 5
  13. Archive-name: nethack31/Part05
  14. Supersedes: nethack3p9: Volume 10, Issue 46-102
  15. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 5 (of 108)."
  26. # Contents:  sys/amiga/colors.uu sys/unix/cpp2.shr
  27. # Wrapped by billr@saab on Wed Jan 27 16:08:46 1993
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'sys/amiga/colors.uu' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'sys/amiga/colors.uu'\"
  31. else
  32. echo shar: Extracting \"'sys/amiga/colors.uu'\" \(1754 characters\)
  33. sed "s/^X//" >'sys/amiga/colors.uu' <<'END_OF_FILE'
  34. Xbegin 777 colors.pw
  35. XM4&]W97)7:6YD;W=S('8R+C5C(*DQ.3@W+"`Q.3@X(&)Y($E.3U9!5%)/3DE#
  36. XM4RP@24Y#+B`@("`@("`@("`@("`@("`@("`@("`@```"[`````E```#\````
  37. XM`0`````!`````!%A;6EG83IC;VQO<G=I;BYC```G_A@``````H``R``"``&`
  38. XM```/```````D\P@```````````````(````!``````$``````0`````,H*"@
  39. XM````\/#PP&"0`````0`"$`X`8`)X``4`!?____\`````````````````````
  40. XM````````````!0`D]Z@```````5#;VQ?```!`*\`+0$=`%``!0`%_____P``
  41. XM`!-%9&ET(%-C<F5E;B!#;VQO<G,``"@)J``'`"0!#P`+`````P`#`"@&0```
  42. XM```````````````H")@````H"8#_____`P``!0`H!B0```````````$0```!
  43. XM$``,````#````````````0<`!P`````````````````````!`P````#_____
  44. XM````"@````L`)3\@`"5":``EVM``)>&0`"7B*``EXM@````(0FQU95!E;@``
  45. XM```!``````$`````"T=!1$),545014X``````0`````!```H"F@`!P`8`0\`
  46. XM"P````,``P`H"@``````````````````*`H@````*`I`_____P,```4`*`GD
  47. XM```````````!$````1``#`````P```````````$'``<`````````````````
  48. XM``````,`````_____P````H````+`"8/\``EZH``)?>(`"8:B``G:B``)VT(
  49. XM````"4=R965N4&5N``````$``````0`````,1T%$1U)%14Y014X``````0``
  50. XM```!```H"U``!P`,`0\`"P````,``P`H"L``````````````````*`K@````
  51. XM*`L`_____P,```4`*`JD```````````!$````1``#`````P```````````$'
  52. XM``<```````````````````````,`````_____P````H````+`">%6``H!2``
  53. XM*`9@`"@+*``H"+@`*`M`````!U)E9%!E;@`````!``````$`````"D=!1%)%
  54. XM1%!%3@`````!``````$``"@,>`#:`$$`.@`+`````P`!`"@+?```````*`NH
  55. XM````````````!@`H#`C_____`P``!0`H"XP````````````[````.P`,````
  56. XM#````````````P`!```&``$``````"@+R``````````'0V%N8V5L``````H`
  57. XM```!`"@+V``H"^@`*`PP`"@,0``H#%@`*`QH````!T-A;F-E;``````!````
  58. XM``$`````#4=!1$-/3$-!3D-%3``````!``````$````````(`$$`.@`+````
  59. XM`P`!`"@,I```````*`S0````````````!P`H#0#_____`P``!0`H#+0`````
  60. XM```````[````.P`,````#````````````P`!```-``$``````"@,\```````
  61. XM```%3VMA>0`````*`````0`H#2@`*`TX`"@-2``H#5@`*`UP`"@-@`````5/
  62. XG:V%Y``````$``````0`````+1T%$0T],3TM!60`````!``````$`
  63. X`
  64. Xend
  65. END_OF_FILE
  66. if test 1754 -ne `wc -c <'sys/amiga/colors.uu'`; then
  67.     echo shar: \"'sys/amiga/colors.uu'\" unpacked with wrong size!
  68. fi
  69. # end of 'sys/amiga/colors.uu'
  70. fi
  71. if test -f 'sys/unix/cpp2.shr' -a "${1}" != "-c" ; then 
  72.   echo shar: Will not clobber existing file \"'sys/unix/cpp2.shr'\"
  73. else
  74. echo shar: Extracting \"'sys/unix/cpp2.shr'\" \(53580 characters\)
  75. sed "s/^X//" >'sys/unix/cpp2.shr' <<'END_OF_FILE'
  76. X#!/bin/sh
  77. X# This is a shell archive.  Save it in a file, remove anything before
  78. X# this line, and then unpack it by entering "sh file".  Note, it may
  79. X# create directories; files and directories will be owned by you and
  80. X# have default permissions.
  81. X#
  82. X# This archive contains:
  83. X#
  84. X#    cpp1.c
  85. X#    cpp3.c
  86. X#    cpp4.c
  87. X#
  88. Xecho x - cpp1.c
  89. Xsed 's/^X//' >cpp1.c << 'END-of-cpp1.c'
  90. XX/*
  91. XX * CPP main program.
  92. XX *
  93. XX * Edit history
  94. XX * 21-May-84    MM    "Field test" release
  95. XX * 23-May-84    MM    Some minor hacks.
  96. XX * 30-May-84    ARF    Didn't get enough memory for __DATE__
  97. XX *            Added code to read stdin if no input
  98. XX *            files are provided.
  99. XX * 29-Jun-84    MM    Added ARF's suggestions, Unixifying cpp.
  100. XX * 11-Jul-84    MM    "Official" first release (that's what I thought!)
  101. XX * 22-Jul-84    MM/ARF/SCK Fixed line number bugs, added cpp recognition
  102. XX *            of #line, fixed problems with #include.
  103. XX * 23-Jul-84    MM    More (minor) include hacking, some documentation.
  104. XX *            Also, redid cpp's #include files
  105. XX * 25-Jul-84    MM    #line filename isn't used for #include searchlist
  106. XX *            #line format is <number> <optional name>
  107. XX * 25-Jul-84    ARF/MM    Various bugs, mostly serious.  Removed homemade doprint
  108. XX * 01-Aug-84    MM    Fixed recursion bug, remove extra newlines and
  109. XX *            leading whitespace from cpp output.
  110. XX * 02-Aug-84    MM    Hacked (i.e. optimized) out blank lines and unneeded
  111. XX *            whitespace in general.  Cleaned up unget()'s.
  112. XX * 03-Aug-84    Keie    Several bug fixes from Ed Keizer, Vrije Universitet.
  113. XX *            -- corrected arg. count in -D and pre-defined
  114. XX *            macros.  Also, allow \n inside macro actual parameter
  115. XX *            lists.
  116. XX * 06-Aug-84    MM    If debugging, dump the preset vector at startup.
  117. XX * 12-Aug-84    MM/SCK    Some small changes from Sam Kendall
  118. XX * 15-Aug-84    Keie/MM    cerror, cwarn, etc. take a single string arg.
  119. XX *            cierror, etc. take a single int. arg.
  120. XX *            changed LINE_PREFIX slightly so it can be
  121. XX *            changed in the makefile.
  122. XX * 31-Aug-84    MM    USENET net.sources release.
  123. XX *  7-Sep-84    SCH/ado Lint complaints
  124. XX * 10-Sep-84    Keie    Char's can't be signed in some implementations
  125. XX * 11-Sep-84    ado    Added -C flag, pathological line number fix
  126. XX * 13-Sep-84    ado    Added -E flag (does nothing) and "-" file for stdin.
  127. XX * 14-Sep-84    MM    Allow # 123 as a synonym for #line 123
  128. XX * 19-Sep-84    MM    scanid always reads to token, make sure #line is
  129. XX *            written to a new line, even if -C switch given.
  130. XX *            Also, cpp - - reads stdin, writes stdout.
  131. XX * 03-Oct-84    ado/MM    Several changes to line counting and keepcomments
  132. XX *            stuff.  Also a rewritten control() hasher -- much
  133. XX *            simpler and no less "perfect". Note also changes
  134. XX *            in cpp3.c to fix numeric scanning.
  135. XX * 04-Oct-84    MM    Added recognition of macro formal parameters if
  136. XX *            they are the only thing in a string, per the
  137. XX *            draft standard.
  138. XX * 08-Oct-84    MM    One more attack on scannumber
  139. XX * 15-Oct-84    MM/ado    Added -N to disable predefined symbols.  Fixed
  140. XX *            linecount if COMMENT_INVISIBLE enabled.
  141. XX * 22-Oct-84    MM    Don't evaluate the #if/#ifdef argument if
  142. XX *            compilation is supressed.  This prevents
  143. XX *            unnecessary error messages in sequences such as
  144. XX *                #ifdef FOO        -- undefined
  145. XX *                #if FOO == 10    -- shouldn't print warning
  146. XX * 25-Oct-84    MM    Fixed bug in false ifdef supression.  On vms,
  147. XX *            #include <foo> should open foo.h -- this duplicates
  148. XX *            the behavior of Vax-C
  149. XX * 31-Oct-84    ado/MM    Parametized $ in indentifiers.  Added a better
  150. XX *            token concatenator and took out the trial
  151. XX *            concatenation code.  Also improved #ifdef code
  152. XX *            and cleaned up the macro recursion tester.
  153. XX *  2-Nov-84    MM/ado    Some bug fixes in token concatenation, also
  154. XX *            a variety of minor (uninteresting) hacks.
  155. XX *  6-Nov-84    MM    Happy Birthday.  Broke into 4 files and added
  156. XX *            #if sizeof (basic_types)
  157. XX *  9-Nov-84    MM    Added -S* for pointer type sizes
  158. XX * 13-Nov-84    MM    Split cpp1.c, added vms defaulting
  159. XX * 23-Nov-84    MM/ado    -E supresses error exit, added CPP_INCLUDE,
  160. XX *            fixed strncpy bug.
  161. XX *  3-Dec-84    ado/MM    Added OLD_PREPROCESSOR
  162. XX *  7-Dec-84    MM    Stuff in Nov 12 Draft Standard
  163. XX * 17-Dec-84    george    Fixed problems with recursive macros
  164. XX * 17-Dec-84    MM    Yet another attack on #if's (f/t)level removed.
  165. XX * 07-Jan-85    ado    Init defines before doing command line options
  166. XX *            so -Uunix works.
  167. XX */
  168. XX
  169. XX/*)BUILD
  170. XX    $(PROGRAM)    = cpp
  171. XX    $(FILES)    = { cpp1 cpp2 cpp3 cpp4 cpp5 cpp6 }
  172. XX    $(INCLUDE)    = { cppdef.h cpp.h }
  173. XX    $(STACK)    = 2000
  174. XX    $(TKBOPTIONS)    = {
  175. XX        STACK    = 2000
  176. XX    }
  177. XX*/
  178. XX
  179. XX#ifdef    DOCUMENTATION
  180. XX
  181. XXtitle    cpp        C Pre-Processor
  182. XXindex            C pre-processor
  183. XX
  184. XXsynopsis
  185. XX    .s.nf
  186. XX    cpp [-options] [infile [outfile]]
  187. XX    .s.f
  188. XXdescription
  189. XX
  190. XX    CPP reads a C source file, expands macros and include
  191. XX    files, and writes an input file for the C compiler.
  192. XX    If no file arguments are given, CPP reads from stdin
  193. XX    and writes to stdout.  If one file argument is given,
  194. XX    it will define the input file, while two file arguments
  195. XX    define both input and output files.  The file name "-"
  196. XX    is a synonym for stdin or stdout as appropriate.
  197. XX
  198. XX    The following options are supported.  Options may
  199. XX    be given in either case.
  200. XX    .lm +16
  201. XX    .p -16
  202. XX    -C        If set, source-file comments are written
  203. XX    to the output file.  This allows the output of CPP to be
  204. XX    used as the input to a program, such as lint, that expects
  205. XX    commands embedded in specially-formatted comments.
  206. XX    .p -16
  207. XX    -Dname=value    Define the name as if the programmer wrote
  208. XX
  209. XX        #define name value
  210. XX
  211. XX    at the start of the first file.  If "=value" is not
  212. XX    given, a value of "1" will be used.
  213. XX
  214. XX    On non-unix systems, all alphabetic text will be forced
  215. XX    to upper-case.
  216. XX    .p -16
  217. XX    -E        Always return "success" to the operating
  218. XX    system, even if errors were detected.  Note that some fatal
  219. XX    errors, such as a missing #include file, will terminate
  220. XX    CPP, returning "failure" even if the -E option is given.
  221. XX    .p -16
  222. XX    -Idirectory    Add this directory to the list of
  223. XX    directories searched for #include "..." and #include <...>
  224. XX    commands.  Note that there is no space between the
  225. XX    "-I" and the directory string.  More than one -I command
  226. XX    is permitted.  On non-Unix systems "directory" is forced
  227. XX    to upper-case.
  228. XX    .p -16
  229. XX    -N        CPP normally predefines some symbols defining
  230. XX    the target computer and operating system.  If -N is specified,
  231. XX    no symbols will be predefined.  If -N -N is specified, the
  232. XX    "always present" symbols, __LINE__, __FILE__, and __DATE__
  233. XX    are not defined.
  234. XX    .p -16
  235. XX    -Stext        CPP normally assumes that the size of
  236. XX    the target computer's basic variable types is the same as the size
  237. XX    of these types of the host computer.  (This can be overridden
  238. XX    when CPP is compiled, however.)  The -S option allows dynamic
  239. XX    respecification of these values.  "text" is a string of
  240. XX    numbers, separated by commas, that specifies correct sizes.
  241. XX    The sizes must be specified in the exact order:
  242. XX
  243. XX        char short int long float double
  244. XX
  245. XX    If you specify the option as "-S*text", pointers to these
  246. XX    types will be specified.  -S* takes one additional argument
  247. XX    for pointer to function (e.g. int (*)())
  248. XX
  249. XX    For example, to specify sizes appropriate for a PDP-11,
  250. XX    you would write:
  251. XX
  252. XX           c s i l f d func
  253. XX         -S1,2,2,2,4,8,
  254. XX        -S*2,2,2,2,2,2,2
  255. XX
  256. XX    Note that all values must be specified.
  257. XX    .p -16
  258. XX    -Uname        Undefine the name as if
  259. XX
  260. XX        #undef name
  261. XX
  262. XX    were given.  On non-Unix systems, "name" will be forced to
  263. XX    upper-case.
  264. XX    .p -16
  265. XX    -Xnumber    Enable debugging code.  If no value is
  266. XX    given, a value of 1 will be used.  (For maintenence of
  267. XX    CPP only.)
  268. XX    .s.lm -16
  269. XX
  270. XXPre-Defined Variables
  271. XX
  272. XX    When CPP begins processing, the following variables will
  273. XX    have been defined (unless the -N option is specified):
  274. XX    .s
  275. XX    Target computer (as appropriate):
  276. XX    .s
  277. XX        pdp11, vax, M68000 m68000 m68k
  278. XX    .s
  279. XX    Target operating system (as appropriate):
  280. XX    .s
  281. XX        rsx, rt11, vms, unix
  282. XX    .s
  283. XX    Target compiler (as appropriate):
  284. XX    .s
  285. XX        decus, vax11c
  286. XX    .s
  287. XX    The implementor may add definitions to this list.
  288. XX    The default definitions match the definition of the
  289. XX    host computer, operating system, and C compiler.
  290. XX    .s
  291. XX    The following are always available unless undefined (or
  292. XX    -N was specified twice):
  293. XX    .lm +16
  294. XX    .p -12
  295. XX    __FILE__    The input (or #include) file being compiled
  296. XX    (as a quoted string).
  297. XX    .p -12
  298. XX    __LINE__    The line number being compiled.
  299. XX    .p -12
  300. XX    __DATE__    The date and time of compilation as
  301. XX    a Unix ctime quoted string (the trailing newline is removed).
  302. XX    Thus,
  303. XX    .s
  304. XX        printf("Bug at line %s,", __LINE__);
  305. XX        printf(" source file %s", __FILE__);
  306. XX        printf(" compiled on %s", __DATE__);
  307. XX    .s.lm -16
  308. XX
  309. XXDraft Proposed Ansi Standard Considerations
  310. XX
  311. XX    The current version of the Draft Proposed Standard
  312. XX    explicitly states that "readers are requested not to specify
  313. XX    or claim conformance to this draft."  Readers and users
  314. XX    of Decus CPP should not assume that Decus CPP conforms
  315. XX    to the standard, or that it will conform to the actual
  316. XX    C Language Standard.
  317. XX
  318. XX    When CPP is itself compiled, many features of the Draft
  319. XX    Proposed Standard that are incompatible with existing
  320. XX    preprocessors may be disabled.  See the comments in CPP's
  321. XX    source for details.
  322. XX
  323. XX    The latest version of the Draft Proposed Standard (as reflected
  324. XX    in Decus CPP) is dated November 12, 1984.
  325. XX
  326. XX    Comments are removed from the input text.  The comment
  327. XX    is replaced by a single space character.  The -C option
  328. XX    preserves comments, writing them to the output file.
  329. XX
  330. XX    The '$' character is considered to be a letter.  This is
  331. XX    a permitted extension.
  332. XX
  333. XX    The following new features of C are processed by CPP:
  334. XX    .s.comment Note: significant spaces, not tabs, .br quotes #if, #elif
  335. XX    .br;####_#elif expression    (_#else _#if)
  336. XX    .br;####'_\xNNN'             (Hexadecimal constant)
  337. XX    .br;####'_\a'                (Ascii BELL)
  338. XX    .br;####'_\v'                (Ascii Vertical Tab)
  339. XX    .br;####_#if defined NAME    1 if defined, 0 if not
  340. XX    .br;####_#if defined (NAME)  1 if defined, 0 if not  
  341. XX    .br;####_#if sizeof (basic type)
  342. XX    .br;####unary +
  343. XX    .br;####123U, 123LU          Unsigned ints and longs.
  344. XX    .br;####12.3L                Long double numbers
  345. XX    .br;####token_#token         Token concatenation
  346. XX    .br;####_#include token      Expands to filename
  347. XX
  348. XX    The Draft Proposed Standard has extended C, adding a constant
  349. XX    string concatenation operator, where
  350. XX
  351. XX        "foo" "bar"
  352. XX
  353. XX    is regarded as the single string "foobar".  (This does not
  354. XX    affect CPP's processing but does permit a limited form of
  355. XX    macro argument substitution into strings as will be discussed.)
  356. XX
  357. XX    The Standard Committee plans to add token concatenation
  358. XX    to #define command lines.  One suggested implementation
  359. XX    is as follows:  the sequence "Token1#Token2" is treated
  360. XX    as if the programmer wrote "Token1Token2".  This could
  361. XX    be used as follows:
  362. XX
  363. XX        #line 123
  364. XX        #define ATLINE foo#__LINE__
  365. XX
  366. XX    ATLINE would be defined as foo123.
  367. XX
  368. XX    Note that "Token2" must either have the format of an
  369. XX    identifier or be a string of digits.  Thus, the string
  370. XX
  371. XX        #define ATLINE foo#1x3
  372. XX
  373. XX    generates two tokens: "foo1" and "x3".
  374. XX
  375. XX    If the tokens T1 and T2 are concatenated into T3,
  376. XX    this implementation operates as follows:
  377. XX
  378. XX      1. Expand T1 if it is a macro.
  379. XX      2. Expand T2 if it is a macro.
  380. XX      3. Join the tokens, forming T3.
  381. XX      4. Expand T3 if it is a macro.
  382. XX
  383. XX    A macro formal parameter will be substituted into a string
  384. XX    or character constant if it is the only component of that
  385. XX    constant:
  386. XX
  387. XX        #define VECSIZE 123
  388. XX        #define vprint(name, size) \
  389. XX          printf("name" "[" "size" "] = {\n")
  390. XX          ... vprint(vector, VECSIZE);
  391. XX
  392. XX    expands (effectively) to
  393. XX
  394. XX          vprint("vector[123] = {\n");
  395. XX
  396. XX    Note that this will be useful if your C compiler supports
  397. XX    the new string concatenation operation noted above.
  398. XX    As implemented here, if you write
  399. XX
  400. XX        #define string(arg) "arg"
  401. XX          ... string("foo") ...
  402. XX
  403. XX    This implementation generates "foo", rather than the strictly
  404. XX    correct ""foo"" (which will probably generate an error message).
  405. XX    This is, strictly speaking, an error in CPP and may be removed
  406. XX    from future releases.
  407. XX
  408. XXerror messages
  409. XX
  410. XX    Many.  CPP prints warning or error messages if you try to
  411. XX    use multiple-byte character constants (non-transportable)
  412. XX    if you #undef a symbol that was not defined, or if your
  413. XX    program has potentially nested comments.
  414. XX
  415. XXauthor
  416. XX
  417. XX    Martin Minow
  418. XX
  419. XXbugs
  420. XX
  421. XX    The #if expression processor uses signed integers only.
  422. XX    I.e, #if 0xFFFFu < 0 may be TRUE.
  423. XX
  424. XX#endif
  425. XX
  426. XX#include    <stdio.h>
  427. XX#include    <ctype.h>
  428. XX#include    "cppdef.h"
  429. XX#include    "cpp.h"
  430. XX
  431. XX/*
  432. XX * Commonly used global variables:
  433. XX * line        is the current input line number.
  434. XX * wrongline    is set in many places when the actual output
  435. XX *        line is out of sync with the numbering, e.g,
  436. XX *        when expanding a macro with an embedded newline.
  437. XX *
  438. XX * token    holds the last identifier scanned (which might
  439. XX *        be a candidate for macro expansion).
  440. XX * errors    is the running cpp error counter.
  441. XX * infile    is the head of a linked list of input files (extended by
  442. XX *        #include and macros being expanded).  infile always points
  443. XX *        to the current file/macro.  infile->parent to the includer,
  444. XX *        etc.  infile->fd is NULL if this input stream is a macro.
  445. XX */
  446. XXint        line;            /* Current line number        */
  447. XXint        wrongline;        /* Force #line to compiler    */
  448. XXchar        token[IDMAX + 1];    /* Current input token        */
  449. XXint        errors;            /* cpp error counter        */
  450. XXFILEINFO    *infile = NULL;        /* Current input file        */
  451. XX#if DEBUG
  452. XXint        debug;            /* TRUE if debugging now    */
  453. XX#endif
  454. XX/*
  455. XX * This counter is incremented when a macro expansion is initiated.
  456. XX * If it exceeds a built-in value, the expansion stops -- this tests
  457. XX * for a runaway condition:
  458. XX *    #define X Y
  459. XX *    #define Y X
  460. XX *    X
  461. XX * This can be disabled by falsifying rec_recover.  (Nothing does this
  462. XX * currently: it is a hook for an eventual invocation flag.)
  463. XX */
  464. XXint        recursion;        /* Infinite recursion counter    */
  465. XXint        rec_recover = TRUE;    /* Unwind recursive macros    */
  466. XX
  467. XX/*
  468. XX * instring is set TRUE when a string is scanned.  It modifies the
  469. XX * behavior of the "get next character" routine, causing all characters
  470. XX * to be passed to the caller (except <DEF_MAGIC>).  Note especially that
  471. XX * comments and \<newline> are not removed from the source.  (This
  472. XX * prevents cpp output lines from being arbitrarily long).
  473. XX *
  474. XX * inmacro is set by #define -- it absorbs comments and converts
  475. XX * form-feed and vertical-tab to space, but returns \<newline>
  476. XX * to the caller.  Strictly speaking, this is a bug as \<newline>
  477. XX * shouldn't delimit tokens, but we'll worry about that some other
  478. XX * time -- it is more important to prevent infinitly long output lines.
  479. XX *
  480. XX * instring and inmarcor are parameters to the get() routine which
  481. XX * were made global for speed.
  482. XX */
  483. XXint        instring = FALSE;    /* TRUE if scanning string    */
  484. XXint        inmacro = FALSE;    /* TRUE if #defining a macro    */
  485. XX
  486. XX/*
  487. XX * work[] and workp are used to store one piece of text in a temporay
  488. XX * buffer.  To initialize storage, set workp = work.  To store one
  489. XX * character, call save(c);  (This will fatally exit if there isn't
  490. XX * room.)  To terminate the string, call save(EOS).  Note that
  491. XX * the work buffer is used by several subroutines -- be sure your
  492. XX * data won't be overwritten.  The extra byte in the allocation is
  493. XX * needed for string formal replacement.
  494. XX */
  495. XXchar        work[NWORK + 1];    /* Work buffer            */
  496. XXchar        *workp;            /* Work buffer pointer        */
  497. XX
  498. XX/*
  499. XX * keepcomments is set TRUE by the -C option.  If TRUE, comments
  500. XX * are written directly to the output stream.  This is needed if
  501. XX * the output from cpp is to be passed to lint (which uses commands
  502. XX * embedded in comments).  cflag contains the permanent state of the
  503. XX * -C flag.  keepcomments is always falsified when processing #control
  504. XX * commands and when compilation is supressed by a false #if
  505. XX *
  506. XX * If eflag is set, CPP returns "success" even if non-fatal errors
  507. XX * were detected.
  508. XX *
  509. XX * If nflag is non-zero, no symbols are predefined except __LINE__.
  510. XX * __FILE__, and __DATE__.  If nflag > 1, absolutely no symbols
  511. XX * are predefined.
  512. XX */
  513. XXint        keepcomments = FALSE;    /* Write out comments flag    */
  514. XXint        cflag = FALSE;        /* -C option (keep comments)    */
  515. XXint        eflag = FALSE;        /* -E option (never fail)    */
  516. XXint        nflag = 0;        /* -N option (no predefines)    */
  517. XX
  518. XX/*
  519. XX * ifstack[] holds information about nested #if's.  It is always
  520. XX * accessed via *ifptr.  The information is as follows:
  521. XX *    WAS_COMPILING    state of compiling flag at outer level.
  522. XX *    ELSE_SEEN    set TRUE when #else seen to prevent 2nd #else.
  523. XX *    TRUE_SEEN    set TRUE when #if or #elif succeeds
  524. XX * ifstack[0] holds the compiling flag.  It is TRUE if compilation
  525. XX * is currently enabled.  Note that this must be initialized TRUE.
  526. XX */
  527. XXchar        ifstack[BLK_NEST] = { TRUE };    /* #if information    */
  528. XXchar        *ifptr = ifstack;        /* -> current ifstack[] */
  529. XX
  530. XX/*
  531. XX * incdir[] stores the -i directories (and the system-specific
  532. XX * #include <...> directories.
  533. XX */
  534. XXchar    *incdir[NINCLUDE];        /* -i directories        */
  535. XXchar    **incend = incdir;        /* -> free space in incdir[]    */
  536. XX
  537. XX/*
  538. XX * This is the table used to predefine target machine and operating
  539. XX * system designators.  It may need hacking for specific circumstances.
  540. XX * Note: it is not clear that this is part of the Ansi Standard.
  541. XX * The -N option supresses preset definitions.
  542. XX */
  543. XXchar    *preset[] = {            /* names defined at cpp start    */
  544. XX#ifdef    MACHINE
  545. XX    MACHINE,
  546. XX#endif
  547. XX#ifdef    SYSTEM
  548. XX    SYSTEM,
  549. XX#endif
  550. XX#ifdef    COMPILER
  551. XX    COMPILER,
  552. XX#endif
  553. XX#if    DEBUG
  554. XX    "decus_cpp",            /* Ourselves!            */
  555. XX#endif
  556. XX    NULL                /* Must be last            */
  557. XX};
  558. XX
  559. XX/*
  560. XX * The value of these predefined symbols must be recomputed whenever
  561. XX * they are evaluated.  The order must not be changed.
  562. XX */
  563. XXchar    *magic[] = {            /* Note: order is important    */
  564. XX    "__LINE__",
  565. XX    "__FILE__",
  566. XX    NULL                /* Must be last            */
  567. XX};
  568. XX
  569. XXmain(argc, argv)
  570. XXint        argc;
  571. XXchar        *argv[];
  572. XX{
  573. XX    register int    i;
  574. XX
  575. XX#if HOST == SYS_VMS
  576. XX    argc = getredirection(argc, argv);    /* vms >file and <file    */
  577. XX#endif
  578. XX    initdefines();                /* O.S. specific def's    */
  579. XX    i = dooptions(argc, argv);        /* Command line -flags    */
  580. XX    switch (i) {
  581. XX    case 3:
  582. XX        /*
  583. XX         * Get output file, "-" means use stdout.
  584. XX         */
  585. XX        if (!streq(argv[2], "-")) {
  586. XX#if HOST == SYS_VMS
  587. XX        /*
  588. XX         * On vms, reopen stdout with "vanilla rms" attributes.
  589. XX         */
  590. XX        if ((i = creat(argv[2], 0, "rat=cr", "rfm=var")) == -1
  591. XX         || dup2(i, fileno(stdout)) == -1) {
  592. XX#else
  593. XX        if (freopen(argv[2], "w", stdout) == NULL) {
  594. XX#endif
  595. XX            perror(argv[2]);
  596. XX            cerror("Can't open output file \"%s\"", argv[2]);
  597. XX            exit(IO_ERROR);
  598. XX        }
  599. XX        }                /* Continue by opening input    */
  600. XX    case 2:                /* One file -> stdin        */
  601. XX        /*
  602. XX         * Open input file, "-" means use stdin.
  603. XX         */
  604. XX        if (!streq(argv[1], "-")) {
  605. XX        if (freopen(argv[1], "r", stdin) == NULL) {
  606. XX            perror(argv[1]);
  607. XX            cerror("Can't open input file \"%s\"", argv[1]);
  608. XX            exit(IO_ERROR);
  609. XX        }
  610. XX        strcpy(work, argv[1]);    /* Remember input filename    */
  611. XX        break;
  612. XX        }                /* Else, just get stdin        */
  613. XX    case 0:                /* No args?            */
  614. XX    case 1:                /* No files, stdin -> stdout    */
  615. XX#if HOST == SYS_UNIX
  616. XX        work[0] = EOS;        /* Unix can't find stdin name    */
  617. XX#else
  618. XX        fgetname(stdin, work);    /* Vax-11C, Decus C know name    */
  619. XX#endif
  620. XX        break;
  621. XX
  622. XX    default:
  623. XX        exit(IO_ERROR);        /* Can't happen            */
  624. XX    }
  625. XX    setincdirs();            /* Setup -I include directories    */
  626. XX    addfile(stdin, work);        /* "open" main input file    */
  627. XX#if DEBUG
  628. XX    if (debug > 0)
  629. XX        dumpdef("preset #define symbols");
  630. XX#endif
  631. XX    cppmain();            /* Process main file        */
  632. XX    if ((i = (ifptr - &ifstack[0])) != 0) {
  633. XX#if OLD_PREPROCESSOR
  634. XX        ciwarn("Inside #ifdef block at end of input, depth = %d", i);
  635. XX#else
  636. XX        cierror("Inside #ifdef block at end of input, depth = %d", i);
  637. XX#endif
  638. XX    }
  639. XX    fclose(stdout);
  640. XX    if (errors > 0) {
  641. XX        fprintf(stderr, (errors == 1)
  642. XX        ? "%d error in preprocessor\n"
  643. XX        : "%d errors in preprocessor\n", errors);
  644. XX        if (!eflag)
  645. XX        exit(IO_ERROR);
  646. XX    }
  647. XX    exit(IO_NORMAL);        /* No errors or -E option set    */
  648. XX}
  649. XX
  650. XXFILE_LOCAL
  651. XXcppmain()
  652. XX/*
  653. XX * Main process for cpp -- copies tokens from the current input
  654. XX * stream (main file, include file, or a macro) to the output
  655. XX * file.
  656. XX */
  657. XX{
  658. XX    register int        c;        /* Current character    */
  659. XX    register int        counter;    /* newlines and spaces    */
  660. XX    extern int        output();    /* Output one character    */
  661. XX
  662. XX    /*
  663. XX     * Explicitly output a #line at the start of cpp output so
  664. XX     * that lint (etc.) knows the name of the original source
  665. XX     * file.  If we don't do this explicitly, we may get
  666. XX     * the name of the first #include file instead.
  667. XX     */
  668. XX    sharp();
  669. XX    /*
  670. XX     * This loop is started "from the top" at the beginning of each line
  671. XX     * wrongline is set TRUE in many places if it is necessary to write
  672. XX     * a #line record.  (But we don't write them when expanding macros.)
  673. XX     *
  674. XX     * The counter variable has two different uses:  at
  675. XX     * the start of a line, it counts the number of blank lines that
  676. XX     * have been skipped over.  These are then either output via
  677. XX     * #line records or by outputting explicit blank lines.
  678. XX      * When expanding tokens within a line, the counter remembers
  679. XX     * whether a blank/tab has been output.  These are dropped
  680. XX     * at the end of the line, and replaced by a single blank
  681. XX     * within lines.
  682. XX     */
  683. XX    for (;;) {
  684. XX        counter = 0;            /* Count empty lines    */
  685. XX        for (;;) {                /* For each line, ...    */
  686. XX        while (type[(c = get())] == SPA) /* Skip leading blanks    */
  687. XX            ;                /* in this line.    */
  688. XX        if (c == '\n')            /* If line's all blank,    */
  689. XX            ++counter;            /* Do nothing now    */
  690. XX        else if (c == '#') {        /* Is 1st non-space '#'    */
  691. XX            keepcomments = FALSE;    /* Don't pass comments    */
  692. XX            counter = control(counter);    /* Yes, do a #command    */
  693. XX            keepcomments = (cflag && compiling);
  694. XX        }
  695. XX        else if (c == EOF_CHAR)        /* At end of file?    */
  696. XX            break;
  697. XX        else if (!compiling) {        /* #ifdef false?    */
  698. XX            skipnl();            /* Skip to newline    */
  699. XX            counter++;            /* Count it, too.    */
  700. XX        }
  701. XX        else {
  702. XX            break;            /* Actual token        */
  703. XX        }
  704. XX        }
  705. XX        if (c == EOF_CHAR)            /* Exit process at    */
  706. XX        break;                /* End of file        */
  707. XX        /*
  708. XX         * If the loop didn't terminate because of end of file, we
  709. XX         * know there is a token to compile.  First, clean up after
  710. XX         * absorbing newlines.  counter has the number we skipped.
  711. XX         */
  712. XX        if ((wrongline && infile->fp != NULL) || counter > 4)
  713. XX        sharp();            /* Output # line number    */
  714. XX        else {                /* If just a few, stuff    */
  715. XX        while (--counter >= 0)        /* them out ourselves    */
  716. XX            putchar('\n');
  717. XX        }
  718. XX        /*
  719. XX         * Process each token on this line.
  720. XX         */
  721. XX        unget();                /* Reread the char.    */
  722. XX        for (;;) {                /* For the whole line,    */
  723. XX        do {                /* Token concat. loop    */
  724. XX            for (counter = 0; (type[(c = get())] == SPA);) {
  725. XX#if COMMENT_INVISIBLE
  726. XX            if (c != COM_SEP)
  727. XX                counter++;
  728. XX#else
  729. XX            counter++;        /* Skip over blanks    */
  730. XX#endif
  731. XX            }
  732. XX            if (c == EOF_CHAR || c == '\n')
  733. XX            goto end_line;        /* Exit line loop    */
  734. XX            else if (counter > 0)    /* If we got any spaces    */
  735. XX            putchar(' ');        /* Output one space    */
  736. XX            c = macroid(c);        /* Grab the token    */
  737. XX        } while (type[c] == LET && catenate());
  738. XX        if (c == EOF_CHAR || c == '\n')    /* From macro exp error    */
  739. XX            goto end_line;        /* Exit line loop    */
  740. XX        switch (type[c]) {
  741. XX        case LET:
  742. XX            fputs(token, stdout);    /* Quite ordinary token    */
  743. XX            break;
  744. XX
  745. XX
  746. XX        case DIG:            /* Output a number    */
  747. XX        case DOT:            /* Dot may begin floats    */
  748. XX            scannumber(c, output);
  749. XX            break;
  750. XX
  751. XX        case QUO:            /* char or string const    */
  752. XX            scanstring(c, output);    /* Copy it to output    */
  753. XX            break;
  754. XX
  755. XX        default:            /* Some other character    */
  756. XX            cput(c);            /* Just output it    */
  757. XX            break;
  758. XX        }                /* Switch ends        */
  759. XX        }                    /* Line for loop    */
  760. XXend_line:   if (c == '\n') {            /* Compiling at EOL?    */
  761. XX        putchar('\n');            /* Output newline, if    */
  762. XX        if (infile->fp == NULL)        /* Expanding a macro,    */
  763. XX            wrongline = TRUE;        /* Output # line later    */
  764. XX        }
  765. XX    }                    /* Continue until EOF    */
  766. XX}
  767. XX
  768. XXoutput(c)
  769. XXint        c;
  770. XX/*
  771. XX * Output one character to stdout -- output() is passed as an
  772. XX * argument to scanstring()
  773. XX */
  774. XX{
  775. XX#if COMMENT_INVISIBLE
  776. XX    if (c != TOK_SEP && c != COM_SEP)
  777. XX#else
  778. XX    if (c != TOK_SEP)
  779. XX#endif
  780. XX        putchar(c);
  781. XX}
  782. XX
  783. XXstatic char    *sharpfilename = NULL;
  784. XX
  785. XXFILE_LOCAL
  786. XXsharp()
  787. XX/*
  788. XX * Output a line number line.
  789. XX */
  790. XX{
  791. XX    register char        *name;
  792. XX
  793. XX    if (keepcomments)            /* Make sure # comes on    */
  794. XX        putchar('\n');            /* a fresh, new line.    */
  795. XX    printf("#%s %d", LINE_PREFIX, line);
  796. XX    if (infile->fp != NULL) {
  797. XX        name = (infile->progname != NULL)
  798. XX        ? infile->progname : infile->filename;
  799. XX        if (sharpfilename == NULL
  800. XX         || sharpfilename != NULL && !streq(name, sharpfilename)) {
  801. XX        if (sharpfilename != NULL)
  802. XX            free(sharpfilename);
  803. XX        sharpfilename = savestring(name);
  804. XX        printf(" \"%s\"", name);
  805. XX         }
  806. XX    }
  807. XX    putchar('\n');
  808. XX    wrongline = FALSE;
  809. XX}
  810. XEND-of-cpp1.c
  811. Xecho x - cpp3.c
  812. Xsed 's/^X//' >cpp3.c << 'END-of-cpp3.c'
  813. XX/*
  814. XX *                C P P 3 . C
  815. XX *
  816. XX *            File open and command line options
  817. XX *
  818. XX * Edit history
  819. XX * 13-Nov-84    MM    Split from cpp1.c
  820. XX */
  821. XX
  822. XX#include    <stdio.h>
  823. XX#include    <ctype.h>
  824. XX#include    "cppdef.h"
  825. XX#include    "cpp.h"
  826. XX#if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX)
  827. XX#include    <signal.h>
  828. XXextern int    abort();        /* For debugging        */
  829. XX#endif
  830. XX
  831. XXint
  832. XXopenfile(filename)
  833. XXchar        *filename;
  834. XX/*
  835. XX * Open a file, add it to the linked list of open files.
  836. XX * This is called only from openfile() above.
  837. XX */
  838. XX{
  839. XX    register FILE        *fp;
  840. XX
  841. XX    if ((fp = fopen(filename, "r")) == NULL) {
  842. XX#if DEBUG
  843. XX        perror(filename);
  844. XX#endif
  845. XX        return (FALSE);
  846. XX    }
  847. XX#if DEBUG
  848. XX    if (debug)
  849. XX        fprintf(stderr, "Reading from \"%s\"\n", filename);
  850. XX#endif
  851. XX    addfile(fp, filename);
  852. XX    return (TRUE);
  853. XX}
  854. XX
  855. XXaddfile(fp, filename)
  856. XXFILE        *fp;            /* Open file pointer        */
  857. XXchar        *filename;        /* Name of the file        */
  858. XX/*
  859. XX * Initialize tables for this open file.  This is called from openfile()
  860. XX * above (for #include files), and from the entry to cpp to open the main
  861. XX * input file.  It calls a common routine, getfile() to build the FILEINFO
  862. XX * structure which is used to read characters.  (getfile() is also called
  863. XX * to setup a macro replacement.)
  864. XX */
  865. XX{
  866. XX    register FILEINFO    *file;
  867. XX    extern FILEINFO        *getfile();
  868. XX
  869. XX    file = getfile(NBUFF, filename);
  870. XX    file->fp = fp;            /* Better remember FILE *    */
  871. XX    file->buffer[0] = EOS;        /* Initialize for first read    */
  872. XX    line = 1;            /* Working on line 1 now    */
  873. XX    wrongline = TRUE;        /* Force out initial #line    */
  874. XX}
  875. XX
  876. XXsetincdirs()
  877. XX/*
  878. XX * Append system-specific directories to the include directory list.
  879. XX * Called only when cpp is started.
  880. XX */
  881. XX{
  882. XX
  883. XX#ifdef    CPP_INCLUDE
  884. XX    *incend++ = CPP_INCLUDE;
  885. XX#define    IS_INCLUDE    1
  886. XX#else
  887. XX#define    IS_INCLUDE    0
  888. XX#endif
  889. XX
  890. XX#if HOST == SYS_UNIX
  891. XX    *incend++ = "/usr/include";
  892. XX#define    MAXINCLUDE    (NINCLUDE - 1 - IS_INCLUDE)
  893. XX#endif
  894. XX
  895. XX#if HOST == SYS_VMS
  896. XX    extern char    *getenv();
  897. XX
  898. XX    if (getenv("C$LIBRARY") != NULL)
  899. XX        *incend++ = "C$LIBRARY:";
  900. XX    *incend++ = "SYS$LIBRARY:";
  901. XX#define    MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  902. XX#endif
  903. XX
  904. XX#if HOST == SYS_RSX
  905. XX    extern int    $$rsts;            /* TRUE on RSTS/E    */
  906. XX    extern int    $$pos;            /* TRUE on PRO-350 P/OS    */
  907. XX    extern int    $$vms;            /* TRUE on VMS compat.    */
  908. XX
  909. XX    if ($$pos) {                /* P/OS?        */
  910. XX        *incend++ = "SY:[ZZDECUSC]";    /* C #includes        */
  911. XX        *incend++ = "LB:[1,5]";        /* RSX library        */
  912. XX    }
  913. XX    else if ($$rsts) {            /* RSTS/E?        */
  914. XX        *incend++ = "SY:@";            /* User-defined account    */
  915. XX        *incend++ = "C:";            /* Decus-C library    */
  916. XX        *incend++ = "LB:[1,1]";        /* RSX library        */
  917. XX    }
  918. XX    else if ($$vms) {            /* VMS compatibility?    */
  919. XX        *incend++ = "C:";
  920. XX    }
  921. XX    else {                    /* Plain old RSX/IAS    */
  922. XX        *incend++ = "LB:[1,1]";
  923. XX    }
  924. XX#define    MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  925. XX#endif
  926. XX
  927. XX#if HOST == SYS_RT11
  928. XX    extern int    $$rsts;            /* RSTS/E emulation?    */
  929. XX
  930. XX    if ($$rsts)
  931. XX        *incend++ = "SY:@";            /* User-defined account    */
  932. XX    *incend++ = "C:";            /* Decus-C library disk    */
  933. XX    *incend++ = "SY:";            /* System (boot) disk    */
  934. XX#define    MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  935. XX#endif
  936. XX}
  937. XX
  938. XXint
  939. XXdooptions(argc, argv)
  940. XXint        argc;
  941. XXchar        *argv[];
  942. XX/*
  943. XX * dooptions is called to process command line arguments (-Detc).
  944. XX * It is called only at cpp startup.
  945. XX */
  946. XX{
  947. XX    register char        *ap;
  948. XX    register DEFBUF        *dp;
  949. XX    register int        c;
  950. XX    int            i, j;
  951. XX    char            *arg;
  952. XX    SIZES            *sizp;        /* For -S        */
  953. XX    int            size;        /* For -S        */
  954. XX    int            isdatum;    /* FALSE for -S*    */
  955. XX    int            endtest;    /* For -S        */
  956. XX
  957. XX    for (i = j = 1; i < argc; i++) {
  958. XX        arg = ap = argv[i];
  959. XX        if (*ap++ != '-' || *ap == EOS)
  960. XX        argv[j++] = argv[i];
  961. XX        else {
  962. XX        c = *ap++;            /* Option byte        */
  963. XX        if (islower(c))            /* Normalize case    */
  964. XX            c = toupper(c);
  965. XX        switch (c) {            /* Command character    */
  966. XX        case 'C':            /* Keep comments    */
  967. XX            cflag = TRUE;
  968. XX            keepcomments = TRUE;
  969. XX            break;
  970. XX
  971. XX        case 'D':            /* Define symbol    */
  972. XX#if HOST != SYS_UNIX
  973. XX            zap_uc(ap);            /* Force define to U.C.    */
  974. XX#endif
  975. XX            /*
  976. XX             * If the option is just "-Dfoo", make it -Dfoo=1
  977. XX             */
  978. XX            while (*ap != EOS && *ap != '=')
  979. XX            ap++;
  980. XX            if (*ap == EOS)
  981. XX            ap = "1";
  982. XX            else
  983. XX            *ap++ = EOS;
  984. XX            /*
  985. XX             * Now, save the word and its definition.
  986. XX             */
  987. XX            dp = defendel(argv[i] + 2, FALSE);
  988. XX            dp->repl = savestring(ap);
  989. XX            dp->nargs = DEF_NOARGS;
  990. XX            break;
  991. XX
  992. XX        case 'E':            /* Ignore non-fatal    */
  993. XX            eflag = TRUE;        /* errors.        */
  994. XX            break;
  995. XX
  996. XX        case 'I':            /* Include directory    */
  997. XX            if (incend >= &incdir[MAXINCLUDE])
  998. XX            cfatal("Too many include directories", NULLST);
  999. XX            *incend++ = ap;
  1000. XX            break;
  1001. XX
  1002. XX        case 'N':            /* No predefineds    */
  1003. XX            nflag++;            /* Repeat to undefine    */
  1004. XX            break;            /* __LINE__, etc.    */
  1005. XX
  1006. XX        case 'S':
  1007. XX            sizp = size_table;
  1008. XX            if (isdatum = (*ap != '*'))    /* If it's just -S,    */
  1009. XX            endtest = T_FPTR;    /* Stop here        */
  1010. XX            else {            /* But if it's -S*    */
  1011. XX            ap++;            /* Step over '*'    */
  1012. XX            endtest = 0;        /* Stop at end marker    */
  1013. XX            }
  1014. XX            while (sizp->bits != endtest && *ap != EOS) {
  1015. XX            if (!isdigit(*ap)) {    /* Skip to next digit    */
  1016. XX                ap++;
  1017. XX                continue;
  1018. XX            }
  1019. XX            size = 0;        /* Compile the value    */
  1020. XX            while (isdigit(*ap)) {
  1021. XX                size *= 10;
  1022. XX                size += (*ap++ - '0');
  1023. XX            }
  1024. XX            if (isdatum)
  1025. XX                sizp->size = size;    /* Datum size        */
  1026. XX            else
  1027. XX                sizp->psize = size;    /* Pointer size        */
  1028. XX            sizp++;
  1029. XX            }
  1030. XX            if (sizp->bits != endtest)
  1031. XX            cwarn("-S, too few values specified in %s", argv[i]);
  1032. XX            else if (*ap != EOS)
  1033. XX            cwarn("-S, too many values, \"%s\" unused", ap);
  1034. XX            break;
  1035. XX
  1036. XX        case 'U':            /* Undefine symbol    */
  1037. XX#if HOST != SYS_UNIX
  1038. XX            zap_uc(ap);
  1039. XX#endif
  1040. XX            if (defendel(ap, TRUE) == NULL)
  1041. XX            cwarn("\"%s\" wasn't defined", ap);
  1042. XX            break;
  1043. XX
  1044. XX#if DEBUG
  1045. XX        case 'X':            /* Debug        */
  1046. XX            debug = (isdigit(*ap)) ? atoi(ap) : 1;
  1047. XX#if (HOST == SYS_VMS || HOST == SYS_UNIX)
  1048. XX            signal(SIGINT, abort);    /* Trap "interrupt"    */
  1049. XX#endif
  1050. XX            fprintf(stderr, "Debug set to %d\n", debug);
  1051. XX            break;
  1052. XX#endif
  1053. XX
  1054. XX        default:            /* What is this one?    */
  1055. XX            cwarn("Unknown option \"%s\"", arg);
  1056. XX            fprintf(stderr, "The following options are valid:\n\
  1057. XX  -C\t\t\tWrite source file comments to output\n\
  1058. XX  -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
  1059. XX  -Idirectory\t\tAdd a directory to the #include search list\n\
  1060. XX  -N\t\t\tDon't predefine target-specific names\n\
  1061. XX  -Stext\t\tSpecify sizes for #if sizeof\n\
  1062. XX  -Usymbol\t\tUndefine symbol\n");
  1063. XX#if DEBUG
  1064. XX            fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
  1065. XX#endif
  1066. XX            break;
  1067. XX        }            /* Switch on all options    */
  1068. XX        }                /* If it's a -option        */
  1069. XX    }                /* For all arguments        */
  1070. XX    if (j > 3) {
  1071. XX        cerror(
  1072. XX        "Too many file arguments.  Usage: cpp [input [output]]",
  1073. XX        NULLST);
  1074. XX    }
  1075. XX    return (j);            /* Return new argc        */
  1076. XX}
  1077. XX
  1078. XX#if HOST != SYS_UNIX
  1079. XXFILE_LOCAL
  1080. XXzap_uc(ap)
  1081. XXregister char    *ap;
  1082. XX/*
  1083. XX * Dec operating systems mangle upper-lower case in command lines.
  1084. XX * This routine forces the -D and -U arguments to uppercase.
  1085. XX * It is called only on cpp startup by dooptions().
  1086. XX */
  1087. XX{
  1088. XX    while (*ap != EOS) {
  1089. XX        /*
  1090. XX         * Don't use islower() here so it works with Multinational
  1091. XX         */
  1092. XX        if (*ap >= 'a' && *ap <= 'z')
  1093. XX        *ap = toupper(*ap);
  1094. XX        ap++;
  1095. XX    }
  1096. XX}
  1097. XX#endif
  1098. XX
  1099. XXinitdefines()
  1100. XX/*
  1101. XX * Initialize the built-in #define's.  There are two flavors:
  1102. XX *     #define decus    1        (static definitions)
  1103. XX *    #define    __FILE__ ??        (dynamic, evaluated by magic)
  1104. XX * Called only on cpp startup.
  1105. XX *
  1106. XX * Note: the built-in static definitions are supressed by the -N option.
  1107. XX * __LINE__, __FILE__, and __DATE__ are always present.
  1108. XX */
  1109. XX{
  1110. XX    register char        **pp;
  1111. XX    register char        *tp;
  1112. XX    register DEFBUF        *dp;
  1113. XX    int            i;
  1114. XX    long            tvec;
  1115. XX    extern char        *ctime();
  1116. XX
  1117. XX    /*
  1118. XX     * Predefine the built-in symbols.  Allow the
  1119. XX     * implementor to pre-define a symbol as "" to
  1120. XX     * eliminate it.
  1121. XX     */
  1122. XX    if (nflag == 0) {
  1123. XX        for (pp = preset; *pp != NULL; pp++) {
  1124. XX        if (*pp[0] != EOS) {
  1125. XX            dp = defendel(*pp, FALSE);
  1126. XX            dp->repl = savestring("1");
  1127. XX            dp->nargs = DEF_NOARGS;
  1128. XX        }
  1129. XX        }
  1130. XX    }
  1131. XX    /*
  1132. XX     * The magic pre-defines (__FILE__ and __LINE__ are
  1133. XX     * initialized with negative argument counts.  expand()
  1134. XX     * notices this and calls the appropriate routine.
  1135. XX     * DEF_NOARGS is one greater than the first "magic" definition.
  1136. XX     */
  1137. XX    if (nflag < 2) {
  1138. XX        for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
  1139. XX        dp = defendel(*pp, FALSE);
  1140. XX        dp->nargs = --i;
  1141. XX        }
  1142. XX#if OK_DATE
  1143. XX        /*
  1144. XX         * Define __DATE__ as today's date.
  1145. XX         */
  1146. XX        dp = defendel("__DATE__", FALSE);
  1147. XX        dp->repl = tp = getmem(27);
  1148. XX        dp->nargs = DEF_NOARGS;
  1149. XX        time(&tvec);
  1150. XX        *tp++ = '"';
  1151. XX        strcpy(tp, ctime(&tvec));
  1152. XX        tp[24] = '"';            /* Overwrite newline    */
  1153. XX#endif
  1154. XX    }
  1155. XX}
  1156. XX
  1157. XX#if HOST == SYS_VMS
  1158. XX/*
  1159. XX * getredirection() is intended to aid in porting C programs
  1160. XX * to VMS (Vax-11 C) which does not support '>' and '<'
  1161. XX * I/O redirection.  With suitable modification, it may
  1162. XX * useful for other portability problems as well.
  1163. XX */
  1164. XX
  1165. XXint
  1166. XXgetredirection(argc, argv)
  1167. XXint        argc;
  1168. XXchar        **argv;
  1169. XX/*
  1170. XX * Process vms redirection arg's.  Exit if any error is seen.
  1171. XX * If getredirection() processes an argument, it is erased
  1172. XX * from the vector.  getredirection() returns a new argc value.
  1173. XX *
  1174. XX * Warning: do not try to simplify the code for vms.  The code
  1175. XX * presupposes that getredirection() is called before any data is
  1176. XX * read from stdin or written to stdout.
  1177. XX *
  1178. XX * Normal usage is as follows:
  1179. XX *
  1180. XX *    main(argc, argv)
  1181. XX *    int        argc;
  1182. XX *    char        *argv[];
  1183. XX *    {
  1184. XX *        argc = getredirection(argc, argv);
  1185. XX *    }
  1186. XX */
  1187. XX{
  1188. XX    register char        *ap;    /* Argument pointer    */
  1189. XX    int            i;    /* argv[] index        */
  1190. XX    int            j;    /* Output index        */
  1191. XX    int            file;    /* File_descriptor     */
  1192. XX    extern int        errno;    /* Last vms i/o error     */
  1193. XX
  1194. XX    for (j = i = 1; i < argc; i++) {   /* Do all arguments    */
  1195. XX        switch (*(ap = argv[i])) {
  1196. XX        case '<':            /* <file        */
  1197. XX        if (freopen(++ap, "r", stdin) == NULL) {
  1198. XX            perror(ap);        /* Can't find file    */
  1199. XX            exit(errno);    /* Is a fatal error    */
  1200. XX        }
  1201. XX        break;
  1202. XX
  1203. XX        case '>':            /* >file or >>file    */
  1204. XX        if (*++ap == '>') {    /* >>file        */
  1205. XX            /*
  1206. XX             * If the file exists, and is writable by us,
  1207. XX             * call freopen to append to the file (using the
  1208. XX             * file's current attributes).  Otherwise, create
  1209. XX             * a new file with "vanilla" attributes as if the
  1210. XX             * argument was given as ">filename".
  1211. XX             * access(name, 2) returns zero if we can write on
  1212. XX             * the specified file.
  1213. XX             */
  1214. XX            if (access(++ap, 2) == 0) {
  1215. XX            if (freopen(ap, "a", stdout) != NULL)
  1216. XX                break;    /* Exit case statement    */
  1217. XX            perror(ap);    /* Error, can't append    */
  1218. XX            exit(errno);    /* After access test    */
  1219. XX            }            /* If file accessable    */
  1220. XX        }
  1221. XX        /*
  1222. XX         * On vms, we want to create the file using "standard"
  1223. XX         * record attributes.  creat(...) creates the file
  1224. XX         * using the caller's default protection mask and
  1225. XX         * "variable length, implied carriage return"
  1226. XX         * attributes. dup2() associates the file with stdout.
  1227. XX         */
  1228. XX        if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  1229. XX         || dup2(file, fileno(stdout)) == -1) {
  1230. XX            perror(ap);        /* Can't create file    */
  1231. XX            exit(errno);    /* is a fatal error    */
  1232. XX        }            /* If '>' creation    */
  1233. XX        break;            /* Exit case test    */
  1234. XX
  1235. XX        default:
  1236. XX        argv[j++] = ap;        /* Not a redirector    */
  1237. XX        break;            /* Exit case test    */
  1238. XX        }
  1239. XX    }                /* For all arguments    */
  1240. XX    argv[j] = NULL;            /* Terminate argv[]    */
  1241. XX    return (j);            /* Return new argc    */
  1242. XX}
  1243. XX#endif
  1244. XX
  1245. XX
  1246. XX
  1247. XEND-of-cpp3.c
  1248. Xecho x - cpp4.c
  1249. Xsed 's/^X//' >cpp4.c << 'END-of-cpp4.c'
  1250. XX/*
  1251. XX *                C P P 4 . C
  1252. XX *        M a c r o  D e f i n i t i o n s
  1253. XX *
  1254. XX * Edit History
  1255. XX * 31-Aug-84    MM    USENET net.sources release
  1256. XX * 04-Oct-84    MM    __LINE__ and __FILE__ must call ungetstring()
  1257. XX *            so they work correctly with token concatenation.
  1258. XX *            Added string formal recognition.
  1259. XX * 25-Oct-84    MM    "Short-circuit" evaluate #if's so that we
  1260. XX *            don't print unnecessary error messages for
  1261. XX *            #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  1262. XX * 31-Oct-84    ado/MM    Added token concatenation
  1263. XX *  6-Nov-84    MM    Split off eval stuff
  1264. XX */
  1265. XX
  1266. XX#include    <stdio.h>
  1267. XX#include    <ctype.h>
  1268. XX#include    "cppdef.h"
  1269. XX#include    "cpp.h"
  1270. XX/*
  1271. XX * parm[], parmp, and parlist[] are used to store #define() argument
  1272. XX * lists.  nargs contains the actual number of parameters stored.
  1273. XX */
  1274. XXstatic char    parm[NPARMWORK + 1];    /* define param work buffer     */
  1275. XXstatic char    *parmp;            /* Free space in parm        */
  1276. XXstatic char    *parlist[LASTPARM];    /* -> start of each parameter    */
  1277. XXstatic int    nargs;            /* Parameters for this macro    */
  1278. XX
  1279. XXdodefine()
  1280. XX/*
  1281. XX * Called from control when a #define is scanned.  This module
  1282. XX * parses formal parameters and the replacement string.  When
  1283. XX * the formal parameter name is encountered in the replacement
  1284. XX * string, it is replaced by a character in the range 128 to
  1285. XX * 128+NPARAM (this allows up to 32 parameters within the
  1286. XX * Dec Multinational range).  If cpp is ported to an EBCDIC
  1287. XX * machine, you will have to make other arrangements.
  1288. XX *
  1289. XX * There is some special case code to distinguish
  1290. XX *    #define foo    bar
  1291. XX * from    #define foo()    bar
  1292. XX *
  1293. XX * Also, we make sure that
  1294. XX *    #define    foo    foo
  1295. XX * expands to "foo" but doesn't put cpp into an infinite loop.
  1296. XX *
  1297. XX * A warning message is printed if you redefine a symbol to a
  1298. XX * different text.  I.e,
  1299. XX *    #define    foo    123
  1300. XX *    #define foo    123
  1301. XX * is ok, but
  1302. XX *    #define foo    123
  1303. XX *    #define    foo    +123
  1304. XX * is not.
  1305. XX *
  1306. XX * The following subroutines are called from define():
  1307. XX * checkparm    called when a token is scanned.  It checks through the
  1308. XX *        array of formal parameters.  If a match is found, the
  1309. XX *        token is replaced by a control byte which will be used
  1310. XX *        to locate the parameter when the macro is expanded.
  1311. XX * textput    puts a string in the macro work area (parm[]), updating
  1312. XX *        parmp to point to the first free byte in parm[].
  1313. XX *        textput() tests for work buffer overflow.
  1314. XX * charput    puts a single character in the macro work area (parm[])
  1315. XX *        in a manner analogous to textput().
  1316. XX */
  1317. XX{
  1318. XX    register int        c;
  1319. XX    register DEFBUF        *dp;        /* -> new definition    */
  1320. XX    int            isredefine;    /* TRUE if redefined    */
  1321. XX    char            *old;        /* Remember redefined    */
  1322. XX    extern int        save();        /* Save char in work[]    */
  1323. XX
  1324. XX    if (type[(c = skipws())] != LET)
  1325. XX        goto bad_define;
  1326. XX    isredefine = FALSE;            /* Set if redefining    */
  1327. XX    if ((dp = lookid(c)) == NULL)        /* If not known now    */
  1328. XX        dp = defendel(token, FALSE);    /* Save the name    */
  1329. XX    else {                    /* It's known:        */
  1330. XX        isredefine = TRUE;            /* Remember this fact    */
  1331. XX        old = dp->repl;            /* Remember replacement    */
  1332. XX        dp->repl = NULL;            /* No replacement now    */
  1333. XX    }
  1334. XX    parlist[0] = parmp = parm;        /* Setup parm buffer    */
  1335. XX    if ((c = get()) == '(') {        /* With arguments?    */
  1336. XX        nargs = 0;                /* Init formals counter    */
  1337. XX        do {                /* Collect formal parms    */
  1338. XX        if (nargs >= LASTPARM)
  1339. XX            cfatal("Too many arguments for macro", NULLST);
  1340. XX        else if ((c = skipws()) == ')')
  1341. XX            break;            /* Got them all        */
  1342. XX        else if (type[c] != LET)    /* Bad formal syntax    */
  1343. XX            goto bad_define;
  1344. XX        scanid(c);            /* Get the formal param    */
  1345. XX        parlist[nargs++] = parmp;    /* Save its start    */
  1346. XX        textput(token);            /* Save text in parm[]    */
  1347. XX        } while ((c = skipws()) == ',');    /* Get another argument    */
  1348. XX        if (c != ')')            /* Must end at )    */
  1349. XX        goto bad_define;
  1350. XX        c = ' ';                /* Will skip to body    */
  1351. XX    }
  1352. XX    else {
  1353. XX        /*
  1354. XX         * DEF_NOARGS is needed to distinguish between
  1355. XX         * "#define foo" and "#define foo()".
  1356. XX         */
  1357. XX        nargs = DEF_NOARGS;            /* No () parameters    */
  1358. XX    }
  1359. XX    if (type[c] == SPA)            /* At whitespace?    */
  1360. XX        c = skipws();            /* Not any more.    */
  1361. XX    workp = work;                /* Replacement put here    */
  1362. XX    inmacro = TRUE;                /* Keep \<newline> now    */
  1363. XX    while (c != EOF_CHAR && c != '\n') {    /* Compile macro body    */
  1364. XX#if OK_CONCAT
  1365. XX        if (c == '#') {            /* Token concatenation?    */
  1366. XX        while (workp > work && type[workp[-1]] == SPA)
  1367. XX            --workp;            /* Erase leading spaces    */
  1368. XX        save(TOK_SEP);            /* Stuff a delimiter    */
  1369. XX        c = skipws();            /* Eat whitespace    */
  1370. XX        if (type[c] == LET)        /* Another token here?    */
  1371. XX            ;                /* Stuff it normally    */
  1372. XX        else if (type[c] == DIG) {    /* Digit string after?    */
  1373. XX            while (type[c] == DIG) {    /* Stuff the digits    */
  1374. XX            save(c);
  1375. XX            c = get();
  1376. XX            }
  1377. XX            save(TOK_SEP);        /* Delimit 2nd token    */
  1378. XX        }
  1379. XX        else {
  1380. XX            ciwarn("Strange character after # (%d.)", c);
  1381. XX        }
  1382. XX        continue;
  1383. XX        }
  1384. XX#endif
  1385. XX        switch (type[c]) {
  1386. XX        case LET:
  1387. XX        checkparm(c, dp);        /* Might be a formal    */
  1388. XX        break;
  1389. XX
  1390. XX        case DIG:                /* Number in mac. body    */
  1391. XX        case DOT:                /* Maybe a float number    */
  1392. XX        scannumber(c, save);        /* Scan it off        */
  1393. XX        break;
  1394. XX
  1395. XX        case QUO:                /* String in mac. body    */
  1396. XX#if STRING_FORMAL
  1397. XX        stparmscan(c, dp);        /* Do string magic    */
  1398. XX#else
  1399. XX        stparmscan(c);
  1400. XX#endif
  1401. XX        break;
  1402. XX
  1403. XX        case BSH:                /* Backslash        */
  1404. XX        save('\\');
  1405. XX        if ((c = get()) == '\n')
  1406. XX            wrongline = TRUE;
  1407. XX        save(c);
  1408. XX        break;
  1409. XX
  1410. XX        case SPA:                /* Absorb whitespace    */
  1411. XX        /*
  1412. XX         * Note: the "end of comment" marker is passed on
  1413. XX         * to allow comments to separate tokens.
  1414. XX         */
  1415. XX        if (workp[-1] == ' ')        /* Absorb multiple    */
  1416. XX            break;            /* spaces        */
  1417. XX        else if (c == '\t')
  1418. XX            c = ' ';            /* Normalize tabs    */
  1419. XX        /* Fall through to store character            */
  1420. XX        default:                /* Other character    */
  1421. XX        save(c);
  1422. XX        break;
  1423. XX        }
  1424. XX        c = get();
  1425. XX    }
  1426. XX    inmacro = FALSE;            /* Stop newline hack    */
  1427. XX    unget();                /* For control check    */
  1428. XX    if (workp > work && workp[-1] == ' ')    /* Drop trailing blank    */
  1429. XX        workp--;
  1430. XX    *workp = EOS;                /* Terminate work    */
  1431. XX    dp->repl = savestring(work);        /* Save the string    */
  1432. XX    dp->nargs = nargs;            /* Save arg count    */
  1433. XX#if DEBUG
  1434. XX    if (debug)
  1435. XX        dumpadef("macro definition", dp);
  1436. XX#endif
  1437. XX    if (isredefine) {            /* Error if redefined    */
  1438. XX        if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
  1439. XX         || (old == NULL && dp->repl != NULL)
  1440. XX         || (old != NULL && dp->repl == NULL)) {
  1441. XX        cerror("Redefining defined variable \"%s\"", dp->name);
  1442. XX        }
  1443. XX        if (old != NULL)            /* We don't need the    */
  1444. XX        free(old);            /* old definition now.    */
  1445. XX    }     
  1446. XX    return;
  1447. XX
  1448. XXbad_define:
  1449. XX    cerror("#define syntax error", NULLST);
  1450. XX    inmacro = FALSE;            /* Stop <newline> hack    */
  1451. XX}
  1452. XX
  1453. XXcheckparm(c, dp)
  1454. XXregister int    c;
  1455. XXDEFBUF        *dp;
  1456. XX/*
  1457. XX * Replace this param if it's defined.  Note that the macro name is a
  1458. XX * possible replacement token.  We stuff DEF_MAGIC in front of the token
  1459. XX * which is treated as a LETTER by the token scanner and eaten by
  1460. XX * the output routine.  This prevents the macro expander from
  1461. XX * looping if someone writes "#define foo foo".
  1462. XX */
  1463. XX{
  1464. XX    register int        i;
  1465. XX    register char        *cp;
  1466. XX
  1467. XX    scanid(c);                /* Get parm to token[]    */
  1468. XX    for (i = 0; i < nargs; i++) {        /* For each argument    */
  1469. XX        if (streq(parlist[i], token)) {    /* If it's known    */
  1470. XX        save(i + MAC_PARM);        /* Save a magic cookie    */
  1471. XX        return;                /* And exit the search    */
  1472. XX        }
  1473. XX    }
  1474. XX    if (streq(dp->name, token))        /* Macro name in body?    */
  1475. XX        save(DEF_MAGIC);            /* Save magic marker    */
  1476. XX    for (cp = token; *cp != EOS;)        /* And save        */
  1477. XX        save(*cp++);            /* The token itself    */
  1478. XX}
  1479. XX
  1480. XX#if STRING_FORMAL
  1481. XXstparmscan(delim, dp)
  1482. XXint        delim;
  1483. XXregister DEFBUF    *dp;
  1484. XX/*
  1485. XX * Scan the string (starting with the given delimiter).
  1486. XX * The token is replaced if it is the only text in this string or
  1487. XX * character constant.  The algorithm follows checkparm() above.
  1488. XX * Note that scanstring() has approved of the string.
  1489. XX */
  1490. XX{
  1491. XX    register int        c;
  1492. XX
  1493. XX    /*
  1494. XX     * Warning -- this code hasn't been tested for a while.
  1495. XX     * It exists only to preserve compatibility with earlier
  1496. XX     * implementations of cpp.  It is not part of the Draft
  1497. XX     * ANSI Standard C language.
  1498. XX     */
  1499. XX    save(delim);
  1500. XX    instring = TRUE;
  1501. XX    while ((c = get()) != delim
  1502. XX         && c != '\n'
  1503. XX         && c != EOF_CHAR) {
  1504. XX        if (type[c] == LET)            /* Maybe formal parm    */
  1505. XX        checkparm(c, dp);
  1506. XX        else {
  1507. XX        save(c);
  1508. XX        if (c == '\\')
  1509. XX            save(get());
  1510. XX        }
  1511. XX    }
  1512. XX    instring = FALSE;
  1513. XX    if (c != delim)
  1514. XX        cerror("Unterminated string in macro body", NULLST);
  1515. XX    save(c);
  1516. XX}
  1517. XX#else
  1518. XXstparmscan(delim)
  1519. XXint        delim;
  1520. XX/*
  1521. XX * Normal string parameter scan.
  1522. XX */
  1523. XX{
  1524. XX    register char        *wp;
  1525. XX    register int        i;
  1526. XX    extern int        save();
  1527. XX
  1528. XX    wp = workp;            /* Here's where it starts    */
  1529. XX    if (!scanstring(delim, save))
  1530. XX        return;            /* Exit on scanstring error    */
  1531. XX    workp[-1] = EOS;        /* Erase trailing quote        */
  1532. XX    wp++;                /* -> first string content byte    */ 
  1533. XX    for (i = 0; i < nargs; i++) {
  1534. XX        if (streq(parlist[i], wp)) {
  1535. XX        *wp++ = MAC_PARM + PAR_MAC;    /* Stuff a magic marker    */
  1536. XX        *wp++ = (i + MAC_PARM);        /* Make a formal marker    */
  1537. XX        *wp = wp[-3];            /* Add on closing quote    */
  1538. XX        workp = wp + 1;            /* Reset string end    */
  1539. XX        return;
  1540. XX        }
  1541. XX    }
  1542. XX    workp[-1] = wp[-1];        /* Nope, reset end quote.    */
  1543. XX}
  1544. XX#endif
  1545. XX
  1546. XXdoundef()
  1547. XX/*
  1548. XX * Remove the symbol from the defined list.
  1549. XX * Called from the #control processor.
  1550. XX */
  1551. XX{
  1552. XX    register int        c;
  1553. XX
  1554. XX    if (type[(c = skipws())] != LET)
  1555. XX        cerror("Illegal #undef argument", NULLST);
  1556. XX    else {
  1557. XX        scanid(c);                /* Get name to token[]    */
  1558. XX        if (defendel(token, TRUE) == NULL) {
  1559. XX        cwarn("Symbol \"%s\" not defined in #undef", token);
  1560. XX        }
  1561. XX    }
  1562. XX}
  1563. XX
  1564. XXtextput(text)
  1565. XXchar        *text;
  1566. XX/*
  1567. XX * Put the string in the parm[] buffer.
  1568. XX */
  1569. XX{
  1570. XX    register int    size;
  1571. XX
  1572. XX    size = strlen(text) + 1;
  1573. XX    if ((parmp + size) >= &parm[NPARMWORK])
  1574. XX        cfatal("Macro work area overflow", NULLST);
  1575. XX    else {
  1576. XX        strcpy(parmp, text);
  1577. XX        parmp += size;
  1578. XX    }
  1579. XX}
  1580. XX
  1581. XXcharput(c)
  1582. XXregister int    c;
  1583. XX/*
  1584. XX * Put the byte in the parm[] buffer.
  1585. XX */
  1586. XX{
  1587. XX    if (parmp >= &parm[NPARMWORK])
  1588. XX        cfatal("Macro work area overflow", NULLST);
  1589. XX    else {
  1590. XX        *parmp++ = c;
  1591. XX    }
  1592. XX}
  1593. XX
  1594. XX/*
  1595. XX *        M a c r o   E x p a n s i o n
  1596. XX */
  1597. XX
  1598. XXstatic DEFBUF    *macro;        /* Catches start of infinite macro    */
  1599. XX
  1600. XXexpand(tokenp)
  1601. XXregister DEFBUF    *tokenp;
  1602. XX/*
  1603. XX * Expand a macro.  Called from the cpp mainline routine (via subroutine
  1604. XX * macroid()) when a token is found in the symbol table.  It calls
  1605. XX * expcollect() to parse actual parameters, checking for the correct number.
  1606. XX * It then creates a "file" containing a single line containing the
  1607. XX * macro with actual parameters inserted appropriately.  This is
  1608. XX * "pushed back" onto the input stream.  (When the get() routine runs
  1609. XX * off the end of the macro line, it will dismiss the macro itself.)
  1610. XX */
  1611. XX{
  1612. XX    register int        c;
  1613. XX    register FILEINFO    *file;
  1614. XX    extern FILEINFO        *getfile();
  1615. XX
  1616. XX#if DEBUG
  1617. XX    if (debug)
  1618. XX        dumpadef("expand entry", tokenp);
  1619. XX#endif
  1620. XX    /*
  1621. XX     * If no macro is pending, save the name of this macro
  1622. XX     * for an eventual error message.
  1623. XX     */
  1624. XX    if (recursion++ == 0)
  1625. XX        macro = tokenp;
  1626. XX    else if (recursion == RECURSION_LIMIT) {
  1627. XX        cerror("Recursive macro definition of \"%s\"", tokenp->name);
  1628. XX        fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
  1629. XX        if (rec_recover) {
  1630. XX        do {
  1631. XX            c = get();
  1632. XX        } while (infile != NULL && infile->fp == NULL);
  1633. XX        unget();
  1634. XX        recursion = 0;
  1635. XX        return;
  1636. XX        }
  1637. XX    }
  1638. XX    /*
  1639. XX     * Here's a macro to expand.
  1640. XX     */
  1641. XX    nargs = 0;                /* Formals counter    */
  1642. XX    parmp = parm;                /* Setup parm buffer    */
  1643. XX    switch (tokenp->nargs) {
  1644. XX    case (-2):                /* __LINE__        */
  1645. XX        sprintf(work, "%d", line);
  1646. XX        ungetstring(work);
  1647. XX        break;
  1648. XX
  1649. XX    case (-3):                /* __FILE__        */
  1650. XX        for (file = infile; file != NULL; file = file->parent) {
  1651. XX        if (file->fp != NULL) {
  1652. XX            sprintf(work, "\"%s\"", (file->progname != NULL)
  1653. XX            ? file->progname : file->filename);
  1654. XX            ungetstring(work);
  1655. XX            break;
  1656. XX        }
  1657. XX        }
  1658. XX        break;
  1659. XX
  1660. XX    default:
  1661. XX        /*
  1662. XX         * Nothing funny about this macro.
  1663. XX         */
  1664. XX        if (tokenp->nargs < 0)
  1665. XX        cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
  1666. XX        while ((c = skipws()) == '\n')    /* Look for (, skipping    */
  1667. XX        wrongline = TRUE;        /* spaces and newlines    */
  1668. XX        if (c != '(') {
  1669. XX        /*
  1670. XX         * If the programmer writes
  1671. XX         *    #define foo() ...
  1672. XX         *    ...
  1673. XX         *    foo [no ()]
  1674. XX         * just write foo to the output stream.
  1675. XX         */
  1676. XX        unget();
  1677. XX        cwarn("Macro \"%s\" needs arguments", tokenp->name);
  1678. XX        fputs(tokenp->name, stdout);
  1679. XX        return;
  1680. XX        }
  1681. XX        else if (expcollect()) {        /* Collect arguments    */
  1682. XX        if (tokenp->nargs != nargs) {    /* Should be an error?    */
  1683. XX            cwarn("Wrong number of macro arguments for \"%s\"",
  1684. XX            tokenp->name);
  1685. XX        }
  1686. XX#if DEBUG
  1687. XX        if (debug)
  1688. XX            dumpparm("expand");
  1689. XX#endif
  1690. XX        }                /* Collect arguments        */
  1691. XX    case DEF_NOARGS:        /* No parameters just stuffs    */
  1692. XX        expstuff(tokenp);        /* Do actual parameters        */
  1693. XX    }                /* nargs switch            */
  1694. XX}
  1695. XX
  1696. XXFILE_LOCAL int
  1697. XXexpcollect()
  1698. XX/*
  1699. XX * Collect the actual parameters for this macro.  TRUE if ok.
  1700. XX */
  1701. XX{
  1702. XX    register int    c;
  1703. XX    register int    paren;            /* For embedded ()'s    */
  1704. XX    extern int    charput();
  1705. XX
  1706. XX    for (;;) {
  1707. XX        paren = 0;                /* Collect next arg.    */
  1708. XX        while ((c = skipws()) == '\n')    /* Skip over whitespace    */
  1709. XX        wrongline = TRUE;        /* and newlines.    */
  1710. XX        if (c == ')') {            /* At end of all args?    */
  1711. XX        /*
  1712. XX         * Note that there is a guard byte in parm[]
  1713. XX         * so we don't have to check for overflow here.
  1714. XX         */
  1715. XX        *parmp = EOS;            /* Make sure terminated    */
  1716. XX        break;                /* Exit collection loop    */
  1717. XX        }
  1718. XX        else if (nargs >= LASTPARM)
  1719. XX        cfatal("Too many arguments in macro expansion", NULLST);
  1720. XX        parlist[nargs++] = parmp;        /* At start of new arg    */
  1721. XX        for (;; c = cget()) {        /* Collect arg's bytes    */
  1722. XX        if (c == EOF_CHAR) {
  1723. XX            cerror("end of file within macro argument", NULLST);
  1724. XX            return (FALSE);        /* Sorry.        */
  1725. XX        }
  1726. XX        else if (c == '\\') {        /* Quote next character    */
  1727. XX            charput(c);            /* Save the \ for later    */
  1728. XX            charput(cget());        /* Save the next char.    */
  1729. XX            continue;            /* And go get another    */
  1730. XX        }
  1731. XX        else if (type[c] == QUO) {    /* Start of string?    */
  1732. XX            scanstring(c, charput);    /* Scan it off        */
  1733. XX            continue;            /* Go get next char    */
  1734. XX        }
  1735. XX        else if (c == '(')        /* Worry about balance    */
  1736. XX            paren++;            /* To know about commas    */
  1737. XX        else if (c == ')') {        /* Other side too    */
  1738. XX            if (paren == 0) {        /* At the end?        */
  1739. XX            unget();        /* Look at it later    */
  1740. XX            break;            /* Exit arg getter.    */
  1741. XX            }
  1742. XX            paren--;            /* More to come.    */
  1743. XX        }
  1744. XX        else if (c == ',' && paren == 0) /* Comma delimits args    */
  1745. XX            break;
  1746. XX        else if (c == '\n')        /* Newline inside arg?    */
  1747. XX            wrongline = TRUE;        /* We'll need a #line    */
  1748. XX        charput(c);            /* Store this one    */
  1749. XX        }                    /* Collect an argument    */
  1750. XX        charput(EOS);            /* Terminate argument    */
  1751. XX#if DEBUG
  1752. XX        if (debug)
  1753. XX            printf("parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
  1754. XX#endif
  1755. XX    }                    /* Collect all args.    */
  1756. XX    return (TRUE);                /* Normal return    */
  1757. XX}
  1758. XX
  1759. XXFILE_LOCAL
  1760. XXexpstuff(tokenp)
  1761. XXDEFBUF        *tokenp;        /* Current macro being expanded    */
  1762. XX/*
  1763. XX * Stuff the macro body, replacing formal parameters by actual parameters.
  1764. XX */
  1765. XX{
  1766. XX    register int    c;            /* Current character    */
  1767. XX    register char    *inp;            /* -> repl string    */
  1768. XX    register char    *defp;            /* -> macro output buff    */
  1769. XX    int        size;            /* Actual parm. size    */
  1770. XX    char        *defend;        /* -> output buff end    */
  1771. XX    int        string_magic;        /* String formal hack    */
  1772. XX    FILEINFO    *file;            /* Funny #include    */
  1773. XX    extern FILEINFO    *getfile();
  1774. XX
  1775. XX    file = getfile(NBUFF, tokenp->name);
  1776. XX    inp = tokenp->repl;            /* -> macro replacement    */
  1777. XX    defp = file->buffer;            /* -> output buffer    */
  1778. XX    defend = defp + (NBUFF - 1);        /* Note its end        */
  1779. XX    if (inp != NULL) {
  1780. XX        while ((c = (*inp++ & 0xFF)) != EOS) {
  1781. XX        if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) {
  1782. XX            string_magic = (c == (MAC_PARM + PAR_MAC));
  1783. XX            if (string_magic)
  1784. XX             c = (*inp++ & 0xFF);
  1785. XX            /*
  1786. XX             * Replace formal parameter by actual parameter string.
  1787. XX             */
  1788. XX            if ((c -= MAC_PARM) < nargs) {
  1789. XX            size = strlen(parlist[c]);
  1790. XX            if ((defp + size) >= defend)
  1791. XX                goto nospace;
  1792. XX            /*
  1793. XX             * Erase the extra set of quotes.
  1794. XX             */
  1795. XX            if (string_magic && defp[-1] == parlist[c][0]) {
  1796. XX                strcpy(defp-1, parlist[c]);
  1797. XX                defp += (size - 2);
  1798. XX            }
  1799. XX            else {
  1800. XX                strcpy(defp, parlist[c]);
  1801. XX                defp += size;
  1802. XX            }
  1803. XX            }
  1804. XX        }
  1805. XX        else if (defp >= defend) {
  1806. XXnospace:        cfatal("Out of space in macro \"%s\" arg expansion",
  1807. XX            tokenp->name);
  1808. XX        }
  1809. XX        else {
  1810. XX            *defp++ = c;
  1811. XX        }
  1812. XX        }
  1813. XX    }
  1814. XX    *defp = EOS;
  1815. XX#if DEBUG
  1816. XX    if (debug > 1)
  1817. XX        printf("macroline: \"%s\"\n", file->buffer);
  1818. XX#endif
  1819. XX}
  1820. XX
  1821. XX#if DEBUG
  1822. XXdumpparm(why)
  1823. XXchar        *why;
  1824. XX/*
  1825. XX * Dump parameter list.
  1826. XX */
  1827. XX{
  1828. XX    register int    i;
  1829. XX
  1830. XX    printf("dump of %d parameters (%d bytes total) %s\n",
  1831. XX        nargs, parmp - parm, why);
  1832. XX    for (i = 0; i < nargs; i++) {
  1833. XX        printf("parm[%d] (%d) = \"%s\"\n",
  1834. XX        i + 1, strlen(parlist[i]), parlist[i]);
  1835. XX    }
  1836. XX}
  1837. XX#endif
  1838. XEND-of-cpp4.c
  1839. Xexit
  1840. X
  1841. END_OF_FILE
  1842. if test 53580 -ne `wc -c <'sys/unix/cpp2.shr'`; then
  1843.     echo shar: \"'sys/unix/cpp2.shr'\" unpacked with wrong size!
  1844. fi
  1845. # end of 'sys/unix/cpp2.shr'
  1846. fi
  1847. echo shar: End of archive 5 \(of 108\).
  1848. cp /dev/null ark5isdone
  1849. MISSING=""
  1850. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  1851. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  1852. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  1853. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  1854. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  1855. 101 102 103 104 105 106 107 108 ; do
  1856.     if test ! -f ark${I}isdone ; then
  1857.     MISSING="${MISSING} ${I}"
  1858.     fi
  1859. done
  1860. if test "${MISSING}" = "" ; then
  1861.     echo You have unpacked all 108 archives.
  1862.     echo "Now execute 'rebuild.sh'"
  1863.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  1864. else
  1865.     echo You still need to unpack the following archives:
  1866.     echo "        " ${MISSING}
  1867. fi
  1868. ##  End of shell archive.
  1869. exit 0
  1870.