home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8707 / 41 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  56.4 KB

  1. From: simpson@trwrb.UUCP (Scott Simpson)
  2. Newsgroups: comp.sources.misc
  3. Subject: LaTeX Index Processor (Part 2 of 2)
  4. Message-ID: <2837@ncoast.UUCP>
  5. Date: 10 Jul 87 02:03:15 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Lines: 2763
  8. Approved: allbery@ncoast.UUCP
  9. X-Archive: comp.sources.misc/8707/41
  10.  
  11. #! /bin/sh
  12. # To extract, remove mail header lines and type "sh filename"
  13. if [ ! -d libprofile ]
  14. then
  15.     mkdir libprofile
  16.     echo mkdir libprofile
  17. fi
  18. echo x - libprofile/Makefile
  19. sed -e 's/^X//' > libprofile/Makefile << '!FaR!OuT!'
  20. X# @(#)Makefile    1.1 (TRW) 1/14/86
  21. XCFLAGS = -O
  22. XOBJECTS = boolean.o free.o has.o read.o space.o write.o
  23. X
  24. X.c.o:
  25. X    ${CC} ${CFLAGS} -c $*.c
  26. X    -ld -r -x $*.o
  27. X    mv a.out $*.o
  28. X
  29. Xall: libprofile.a
  30. X
  31. Xlibprofile.a: ${OBJECTS}
  32. X    ar cr libprofile.a ${OBJECTS}
  33. X    ranlib libprofile.a
  34. X    chmod 644 libprofile.a
  35. X
  36. Xinstall: all
  37. X
  38. Xclean:
  39. X    rm -f *.o *.a
  40. !FaR!OuT!
  41. if [ ! -d libprofile ]
  42. then
  43.     mkdir libprofile
  44.     echo mkdir libprofile
  45. fi
  46. echo x - libprofile/boolean.c
  47. sed -e 's/^X//' > libprofile/boolean.c << '!FaR!OuT!'
  48. Xstatic char *trwsccs = "@(#)boolean.c    1.1 (TRW) 1/14/86";
  49. X#include <ctype.h>
  50. X#include "profile.h"
  51. X
  52. Xstatic char *Yes[] = {
  53. X    "yes",
  54. X    "on",
  55. X    "true",
  56. X    "enable",
  57. X    "available",
  58. X    "present",
  59. X    0
  60. X};
  61. X
  62. Xstatic char *No[] = {
  63. X    "no",
  64. X    "off",
  65. X    "false",
  66. X    "disable",
  67. X    "unavailable",
  68. X    "absent",
  69. X    0
  70. X};
  71. X
  72. Xint profile_boolean (v)
  73. XPROFILE_VALUE *v;
  74. X{
  75. X    char x[16];
  76. X    int i;
  77. X
  78. X    if (v == 0)
  79. X        return(0);
  80. X
  81. X    switch (v->class) {
  82. X    case PROFILE_OTHER:
  83. X    case PROFILE_STRING:
  84. X        strncpy(x, v->value.s, sizeof(x)-1);
  85. X        x[sizeof(x)-1] = 0;
  86. X        downshift(x);
  87. X        for (i = 0; Yes[i]; i++)
  88. X            if (strcmp(x, Yes[i]) == 0)
  89. X                return(1);
  90. X            else if (strcmp(x, No[i]) == 0)
  91. X                return(0);
  92. X        return(-1);    /* unknown string */
  93. X
  94. X    case PROFILE_HEX:
  95. X    case PROFILE_INTEGER:
  96. X    case PROFILE_OCTAL:
  97. X        return(v->value.i != 0);
  98. X
  99. X    case PROFILE_CHARACTER:
  100. X        return(v->value.c != 0);
  101. X
  102. X    case PROFILE_FLOAT:
  103. X        return(v->value.f != 0.0);
  104. X
  105. X    default:
  106. X        return(-1);    /* unknown class */
  107. X    }
  108. X}
  109. X
  110. X/* downshift a string in place */
  111. Xstatic downshift (s)
  112. Xchar *s;
  113. X{
  114. X    for (; *s; s++)
  115. X        if (isupper(*s))
  116. X            *s = tolower(*s);
  117. X}
  118. !FaR!OuT!
  119. if [ ! -d libprofile ]
  120. then
  121.     mkdir libprofile
  122.     echo mkdir libprofile
  123. fi
  124. echo x - libprofile/free.c
  125. sed -e 's/^X//' > libprofile/free.c << '!FaR!OuT!'
  126. Xstatic char *trwsccs = "@(#)free.c    1.1 (TRW) 1/14/86";
  127. X#include "profile.h"
  128. X
  129. Xprofile_free_profile (s)
  130. XPROFILE_STANZA *s;
  131. X{
  132. X    PROFILE_STANZA *x;
  133. X
  134. X    for (x = s; x != (PROFILE_STANZA *)0 && x != s; x = x->next)
  135. X        profile_free_stanza(x);
  136. X}
  137. X
  138. Xprofile_free_stanza (s)
  139. XPROFILE_STANZA *s;
  140. X{
  141. X    free_markers(s->marker);
  142. X    free_bindings(s->binding);
  143. X    free(s);
  144. X}
  145. X
  146. Xstatic free_markers (m)
  147. XPROFILE_MARKER *m;
  148. X{
  149. X    PROFILE_MARKER *x;
  150. X
  151. X    for (; m; m = x) {
  152. X        x = m->next;
  153. X        free(m);
  154. X    }
  155. X}
  156. X
  157. Xstatic free_bindings (b)
  158. XPROFILE_BINDING *b;
  159. X{
  160. X    PROFILE_BINDING *x;
  161. X
  162. X    for (; b; b = x) {
  163. X        x = b->next;
  164. X        free_values(b->value);
  165. X        free(b);
  166. X    }
  167. X}
  168. X
  169. Xstatic free_values (v)
  170. XPROFILE_VALUE *v;
  171. X{
  172. X    PROFILE_VALUE *x;
  173. X
  174. X    for (; v; v = x) {
  175. X        x = v->next;
  176. X        free(v);
  177. X    }
  178. X}
  179. !FaR!OuT!
  180. if [ ! -d libprofile ]
  181. then
  182.     mkdir libprofile
  183.     echo mkdir libprofile
  184. fi
  185. echo x - libprofile/has.c
  186. sed -e 's/^X//' > libprofile/has.c << '!FaR!OuT!'
  187. Xstatic char *trwsccs = "@(#)has.c    1.1 (TRW) 1/14/86";
  188. X#include <stdio.h>
  189. X#include "profile.h"
  190. X
  191. XPROFILE_MARKER *profile_has_marker (s, m)
  192. XPROFILE_STANZA *s;
  193. Xchar *m;
  194. X{
  195. X    PROFILE_MARKER *x;
  196. X    int result;
  197. X
  198. X    for (x = s->marker; x; x = x->next)
  199. X        if(glob_match(x->text, m) > 0)
  200. X            return(x);
  201. X    return((PROFILE_MARKER *)0);
  202. X}
  203. X
  204. X/*
  205. X * read down a linked list of stanzas looking
  206. X * for a stanza that has the requested markers
  207. X */
  208. XPROFILE_STANZA *profile_has_stanza(s, marker)
  209. XPROFILE_STANZA *s;
  210. Xchar *marker[];        /* terminated by a null pointer */
  211. X{
  212. X    int i;
  213. X    PROFILE_STANZA *x;
  214. X
  215. X    if (s == NULL)
  216. X        return(s);
  217. X    x = s;
  218. X    do {
  219. X        for (i = 0; marker[i] != NULL; i++)
  220. X            if (profile_has_marker(x, marker[i]) == NULL)
  221. X                break;
  222. X        if (marker[i] == NULL)
  223. X            return(x);
  224. X        x = x->next;
  225. X    } while (x != s && x != NULL);
  226. X
  227. X    return((PROFILE_STANZA *)NULL);
  228. X}
  229. X
  230. XPROFILE_BINDING *profile_has_binding (s, b)
  231. XPROFILE_STANZA *s;
  232. Xchar *b;
  233. X{
  234. X    PROFILE_BINDING *x;
  235. X
  236. X    for (x = s->binding; x; x = x->next)
  237. X        if (glob_match(x->name, b) > 0)
  238. X            return(x);
  239. X    return((PROFILE_BINDING *)0);
  240. X}
  241. !FaR!OuT!
  242. if [ ! -d libprofile ]
  243. then
  244.     mkdir libprofile
  245.     echo mkdir libprofile
  246. fi
  247. echo x - libprofile/profile.h
  248. sed -e 's/^X//' > libprofile/profile.h << '!FaR!OuT!'
  249. X/* @(#)profile.h    1.1 (TRW) 1/14/86 */
  250. Xtypedef struct PROFILE_VALUE {
  251. X    char class;
  252. X    union {
  253. X        long int i;
  254. X        double f;
  255. X        char c;
  256. X        char *s;
  257. X    } value;
  258. X    struct PROFILE_VALUE *previous;
  259. X    struct PROFILE_VALUE *next;
  260. X} PROFILE_VALUE;
  261. X
  262. Xtypedef struct PROFILE_BINDING {
  263. X    char *name;
  264. X    PROFILE_VALUE *value;
  265. X    struct PROFILE_BINDING *previous;
  266. X    struct PROFILE_BINDING *next;
  267. X} PROFILE_BINDING;
  268. X
  269. Xtypedef struct PROFILE_MARKER {
  270. X    char *text;
  271. X    struct PROFILE_MARKER *previous;
  272. X    struct PROFILE_MARKER *next;
  273. X} PROFILE_MARKER;
  274. X
  275. Xtypedef struct PROFILE_STANZA {
  276. X    PROFILE_MARKER *marker;
  277. X    PROFILE_BINDING *binding;
  278. X    struct PROFILE_STANZA *previous;
  279. X    struct PROFILE_STANZA *next;
  280. X} PROFILE_STANZA;
  281. X
  282. X/* classes */
  283. X#define PROFILE_INTEGER 01
  284. X#define PROFILE_FLOAT 02
  285. X#define PROFILE_STRING 03
  286. X#define PROFILE_CHARACTER 04
  287. X#define PROFILE_OTHER 05
  288. X#define PROFILE_OCTAL 06
  289. X#define PROFILE_HEX 07
  290. X
  291. X/* no single lexical element may exceed this size in characters */
  292. X#define PROFILE_MAX_TEXT 255
  293. X
  294. XPROFILE_STANZA *profile_read_stanza();
  295. XPROFILE_STANZA *profile_read_profile();
  296. XPROFILE_MARKER *profile_has_marker();
  297. XPROFILE_STANZA *profile_has_stanza();
  298. XPROFILE_BINDING *profile_has_binding();
  299. XPROFILE_STANZA *profile_stanza_space();
  300. XPROFILE_MARKER *profile_marker_space();
  301. XPROFILE_BINDING *profile_binding_space();
  302. XPROFILE_VALUE *profile_value_space();
  303. !FaR!OuT!
  304. if [ ! -d libprofile ]
  305. then
  306.     mkdir libprofile
  307.     echo mkdir libprofile
  308. fi
  309. echo x - libprofile/read.c
  310. sed -e 's/^X//' > libprofile/read.c << '!FaR!OuT!'
  311. Xstatic char *trwrcs = "$Header: read.c,v 1.1 87/03/16 14:00:10 control Exp $";
  312. Xstatic char *trwsccs = "@(#)read.c    1.1 (TRW) 1/14/86";
  313. X#include <stdio.h>
  314. X#include <ctype.h>
  315. X#include "profile.h"
  316. X
  317. X#define isoctal(d) ('0' <= d && d <= '7')
  318. X#define ishex(x) (isdigit(x) || ('a' <= x && x <= 'f') || ('A' <= x && x <= 'F'))
  319. X#define isprime(c) (c == '\'')
  320. X#define isbackslash(c) (c == '\\')
  321. X#define iscaret(c) (c == '^')
  322. X
  323. Xextern char *strcpy();
  324. Xextern PROFILE_STANZA *profile_stanza_space();
  325. Xextern PROFILE_MARKER *profile_marker_space();
  326. Xextern PROFILE_BINDING *profile_binding_space();
  327. Xextern PROFILE_VALUE *profile_value_space();
  328. X
  329. Xstatic PROFILE_BINDING *get_binding();
  330. Xstatic PROFILE_BINDING *get_bindings();
  331. Xstatic PROFILE_MARKER *get_marker();
  332. Xstatic PROFILE_MARKER *get_markers();
  333. Xstatic PROFILE_VALUE *get_value();
  334. Xstatic PROFILE_VALUE *get_values();
  335. Xstatic char parse_character();
  336. Xstatic PROFILE_VALUE *parse_value();
  337. X
  338. XPROFILE_STANZA *profile_read_stanza (f)
  339. XFILE *f;
  340. X{
  341. X    PROFILE_STANZA *stanza;
  342. X
  343. X    stanza = profile_stanza_space();
  344. X    if (stanza == NULL)
  345. X        return(NULL);
  346. X    stanza->marker = get_markers(f);
  347. X    if (get_open_bindings(f))
  348. X        stanza->binding = get_bindings(f);
  349. X    else {
  350. X        profile_free_stanza(stanza);
  351. X        return(NULL);
  352. X    }
  353. X    if (get_close_bindings(f))
  354. X        return(stanza);
  355. X    else {
  356. X        profile_free_stanza(stanza);
  357. X        return(NULL);
  358. X    }
  359. X}
  360. X
  361. X/* Returns the list of markers at the head of a stanza. */
  362. Xstatic PROFILE_MARKER *get_markers (f)
  363. XFILE *f;
  364. X{
  365. X    PROFILE_MARKER *head, *tail, *m;
  366. X
  367. X    head = tail = NULL;
  368. X    while (m = get_marker(f))
  369. X        if (tail) {
  370. X            tail->next = m;
  371. X            m->previous = tail;
  372. X            tail = m;
  373. X        } else
  374. X            head = tail = m;
  375. X    return(head);
  376. X}
  377. X
  378. X/* Returns the next marker from the head of the stanza. */
  379. Xstatic PROFILE_MARKER *get_marker (f)
  380. XFILE *f;
  381. X{
  382. X    int n;
  383. X    PROFILE_MARKER *m;
  384. X    char scratch[PROFILE_MAX_TEXT+1];
  385. X
  386. X    for (;;)
  387. X        if (n = get_name_text(f, scratch)) {
  388. X            if ((m = profile_marker_space(n)) == NULL)
  389. X                return(NULL);
  390. X            strcpy(m->text, scratch);
  391. X            return(m);
  392. X        } else if (get_end_of_line(f))
  393. X            continue;
  394. X        else
  395. X            return(NULL);
  396. X}
  397. X
  398. X/* Returns the list of bindings in the body of the stanza. */
  399. Xstatic PROFILE_BINDING *get_bindings (f)
  400. XFILE *f;
  401. X{
  402. X    PROFILE_BINDING *head, *tail, *b;
  403. X
  404. X    head = tail = NULL;
  405. X    while (b = get_binding(f))
  406. X        if (tail) {
  407. X            tail->next = b;
  408. X            b->previous = tail;
  409. X            tail = b;
  410. X        } else
  411. X            head = tail = b;
  412. X    return(head);
  413. X}
  414. X
  415. X/* Returns the next binding in the body of the stanza. */
  416. Xstatic PROFILE_BINDING *get_binding (f)
  417. XFILE *f;
  418. X{
  419. X    int n;
  420. X    PROFILE_BINDING *b;
  421. X    char scratch[PROFILE_MAX_TEXT+1];
  422. X
  423. X    for (;;)
  424. X        if (n = get_name_text(f, scratch)) {
  425. X            if ((b = profile_binding_space(n)) == NULL)
  426. X                return(NULL);
  427. X            strcpy(b->name, scratch);
  428. X            break;
  429. X        } else if (get_end_of_line(f))
  430. X            continue;
  431. X        else
  432. X            return(NULL);
  433. X    b->value = get_values(f);
  434. X    return(b);
  435. X}
  436. X
  437. X/* Returns the list of values following the name of the binding. */
  438. Xstatic PROFILE_VALUE *get_values (f)
  439. XFILE *f;
  440. X{
  441. X    PROFILE_VALUE *head, *tail, *v;
  442. X
  443. X    head = tail = NULL;
  444. X    while (v = get_value(f))
  445. X        if (tail) {
  446. X            tail->next = v;
  447. X            v->previous = tail;
  448. X            tail = v;
  449. X        } else
  450. X            head = tail = v;
  451. X    return(head);
  452. X}
  453. X
  454. X/* Returns the next value in the binding. */
  455. Xstatic PROFILE_VALUE *get_value (f)
  456. XFILE *f;
  457. X{
  458. X    char text[PROFILE_MAX_TEXT+1];
  459. X    int n;
  460. X
  461. X    for (;;)
  462. X        if (n = get_value_text(f, text))
  463. X            return(parse_value(text, n));
  464. X        else if (get_end_of_line(f))
  465. X            return(NULL);
  466. X        else
  467. X            return(NULL);
  468. X}
  469. X
  470. X/*
  471. X * Reads the text of the next value (if any) in the binding.  Returns
  472. X * the length of the literal text in characters.
  473. X */
  474. Xstatic int get_value_text (f, text)
  475. XFILE *f;
  476. Xchar *text;
  477. X{
  478. X    register int c;
  479. X    char *s = text;
  480. X
  481. X    while ((c = getc(f)) != EOF)
  482. X        switch (c) {
  483. X        case '\b': case '\f':
  484. X        case '\r': case '\t': case ' ':
  485. X            /* white space terminates any text gathered so far */
  486. X            if (s > text) {
  487. X                *s = '\0';
  488. X                return(s - text);
  489. X            }
  490. X            continue;
  491. X
  492. X        case '\n':
  493. X            /* newline terminates a binding */
  494. X            ungetc(c, f);
  495. X            *s = '\0';
  496. X            return(s - text);
  497. X
  498. X        case '#':
  499. X            /* gobble up the comment */
  500. X            while ((c = getc(f)) != EOF && c != '\n')
  501. X                continue;
  502. X            if (c == '\n')
  503. X                ungetc(c, f);
  504. X            *s = '\0';
  505. X            return(s - text);
  506. X
  507. X        case '{': case '}':
  508. X            ungetc(c, f);
  509. X            *s = '\0';
  510. X            return(s - text);
  511. X
  512. X        case '"':        /* string quotes */
  513. X            ungetc(c, f);
  514. X            if (s > text) {
  515. X                *s = '\0';
  516. X                return(s - text);
  517. X            } else
  518. X                return(get_string(f, s));
  519. X
  520. X        case '\'':        /* character quotes */
  521. X            ungetc(c, f);
  522. X            if (s > text) {
  523. X                *s = '\0';
  524. X                return(s - text);
  525. X            } else
  526. X                return(get_character(f, s));
  527. X
  528. X        case '\\':        /* newline escape */
  529. X            c = getc(f);
  530. X            if (c == '\n') {
  531. X                if (s > text) {
  532. X                    *s = '\0';
  533. X                    return(s - text);
  534. X                }
  535. X                continue;    /* just like a blank */
  536. X            }
  537. X            ungetc(c, f);
  538. X            if (s < &text[PROFILE_MAX_TEXT])
  539. X                *s++ = '\\';
  540. X            continue;
  541. X
  542. X        default:
  543. X            if (s < &text[PROFILE_MAX_TEXT])
  544. X                *s++ = c;
  545. X            continue;
  546. X        }
  547. X    *s = '\0';
  548. X    return(s - text);
  549. X}
  550. X
  551. X/* Digests the raw value text returning a new value structure. */
  552. Xstatic PROFILE_VALUE *parse_value (s, length)
  553. Xchar *s;        /* literal text */
  554. Xint length;        /* in characters */
  555. X{
  556. X    PROFILE_VALUE *v;
  557. X
  558. X    if (is_integer(s)) {
  559. X        if ((v = profile_value_space(0)) == NULL)
  560. X            return(NULL);
  561. X        v->class = PROFILE_INTEGER;
  562. X        sscanf(s, "%D", &v->value.i);
  563. X    } else if (is_octal(s)) {
  564. X        if ((v = profile_value_space(0)) == NULL)
  565. X            return(NULL);
  566. X        v->class = PROFILE_OCTAL;
  567. X        /* skip the `0o' prefix */
  568. X        sscanf(s+2, "%O", &v->value.i);
  569. X    } else if (is_hex(s)) {
  570. X        if ((v = profile_value_space(0)) == NULL)
  571. X            return(NULL);
  572. X        v->class = PROFILE_HEX;
  573. X        /* skip the `0x' prefix */
  574. X        sscanf(s+2, "%X", &v->value.i);
  575. X    } else if (is_string(s)) {
  576. X        /* be careful when dealing with the empty string "" */
  577. X        if ((v = profile_value_space(length > 2 ? length - 2 : 1)) == NULL)
  578. X            return(NULL);
  579. X        v->class = PROFILE_STRING;
  580. X        /* erase the terminating double quote */
  581. X        s[length - 1] = '\0';
  582. X        /* skip past the initial quote */
  583. X        parse_string(s + 1, v->value.s);
  584. X    } else if (is_character(s)) {
  585. X        if ((v = profile_value_space(0)) == NULL)
  586. X            return(NULL);
  587. X        v->class = PROFILE_CHARACTER;
  588. X        /* erase the end single quote */
  589. X        s[length - 1] = '\0';
  590. X        v->value.c = parse_character(s + 1);
  591. X    } else if (is_float(s)) {
  592. X        if ((v = profile_value_space(0)) == NULL)
  593. X            return(NULL);
  594. X        v->class = PROFILE_FLOAT;
  595. X        sscanf(s, "%E", &v->value.f);
  596. X    } else {
  597. X        if ((v = profile_value_space(length)) == NULL)
  598. X            return(NULL);
  599. X        v->class = PROFILE_OTHER;
  600. X        strcpy(v->value.s, s);
  601. X    }
  602. X    return(v);
  603. X}
  604. X
  605. X/* Converts a string literal to the internal representation. */
  606. Xstatic parse_string (source, result)
  607. Xchar *source;
  608. Xchar *result;
  609. X{
  610. X    for (; *source; source++)
  611. X        if (*source == '\\')
  612. X            switch (*++source) {
  613. X            case 'b':            /* backspace */
  614. X                *result++ = '\b';
  615. X                continue;
  616. X            case 'f':            /* formfeed */
  617. X                *result++ = '\f';
  618. X                continue;
  619. X            case 'n':            /* newline */
  620. X                *result++ = '\n';
  621. X                continue;
  622. X            case 'r':            /* carriage return */
  623. X                *result++ = '\r';
  624. X                continue;
  625. X            case 't':            /* horizontal tab */
  626. X                *result++ = '\t';
  627. X                continue;
  628. X            case '\'':            /* single quote */
  629. X                *result++ = '\'';
  630. X                continue;
  631. X            case '"':            /* double quote */
  632. X                *result++ = '"';
  633. X                continue;
  634. X            case '\\':            /* backslash */
  635. X                *result++ = '\\';
  636. X                continue;            
  637. X            case '^':            /* caret */
  638. X                *result++ = '^';
  639. X                continue;
  640. X            case '0': case '1':        /* octal constant */
  641. X            case '2': case '3':
  642. X            case '4': case '5':
  643. X            case '6': case '7':
  644. X                source += parse_octal(source, result) - 2;
  645. X                result++;
  646. X                continue;
  647. X            default:
  648. X                *result++ = *source;    /* ignore backslash */
  649. X            }
  650. X        else if (*source == '^') {    /* control escape */
  651. X            char c = *++source;
  652. X            *result++ = ('@' <= c && c <= '_') ? c - '@' :
  653. X                    (c == '?') ? '\177' : c;
  654. X            continue;
  655. X        } else
  656. X            *result++ = *source;
  657. X    *result = '\0';
  658. X}
  659. X
  660. X/* Converts a character literal to the internal representation. */
  661. Xstatic char parse_character (source)
  662. Xchar *source;
  663. X{
  664. X    char c;
  665. X
  666. X    if (*source == '\\')
  667. X        switch (*++source) {
  668. X        case 'b':            /* backspace */
  669. X            return('\b');
  670. X        case 'f':            /* formfeed */
  671. X            return('\f');
  672. X        case 'n':            /* newline */
  673. X            return('\n');
  674. X        case 'r':            /* carriage return */
  675. X            return('\r');
  676. X        case 't':            /* horizontal tab */
  677. X            return('\t');
  678. X        case '\'':            /* single quote */
  679. X            return('\'');
  680. X        case '\\':            /* backslash */
  681. X            return('\\');
  682. X        case '^':
  683. X            return('^');
  684. X        case '0': case '1':        /* octal constant */
  685. X        case '2': case '3':
  686. X        case '4': case '5':
  687. X        case '6': case '7':
  688. X            parse_octal(source, &c);
  689. X            return(c);
  690. X        default:
  691. X            return(*source);    /* ignore backslash */
  692. X        }
  693. X    else if (*source == '^') {    /* control escape */
  694. X        c = *++source;
  695. X        return(('@' <= c && c <= '_') ? c - '@' : (c == '?') ? '\177' : c);
  696. X    } else
  697. X        return(*source);
  698. X}
  699. X
  700. X/* Converts an octal escape `\ddd' to its byte representation. */
  701. Xstatic int parse_octal (source, result)
  702. Xchar *source;
  703. Xchar *result;
  704. X{
  705. X    int count;
  706. X    char byte = '\0';
  707. X    char digit;
  708. X
  709. X    for (count = 1; count <= 3; count++) {
  710. X        digit = *source++;
  711. X        if ('0' <= digit && digit <= '7')
  712. X            byte = (byte * 8) + (digit - '0');
  713. X        else
  714. X            break;
  715. X    }
  716. X    *result = byte;
  717. X    return(count);
  718. X}
  719. X
  720. X/*
  721. X * Reads the literal text for markers and binding names.  Returns the
  722. X * length in characters of the literal text.
  723. X */
  724. Xstatic int get_name_text (f, text)
  725. XFILE *f;
  726. Xchar *text;
  727. X{
  728. X    register int c;
  729. X    char *s = text;
  730. X
  731. X    while ((c = getc(f)) != EOF)
  732. X        switch (c) {
  733. X        case '\b': case '\f':
  734. X        case '\r': case '\t': case ' ':
  735. X            /* white space terminates text gathered so far */
  736. X            if (s > text) {
  737. X                *s = '\0';
  738. X                return(s - text);
  739. X            }
  740. X            continue;
  741. X
  742. X        case '\n':
  743. X            ungetc(c, f);
  744. X            *s = '\0';
  745. X            return(s - text);
  746. X
  747. X        case '#':
  748. X            /* gobble up the comment */
  749. X            while ((c = getc(f)) != EOF && c != '\n')
  750. X                continue;
  751. X            if (c == '\n')
  752. X                ungetc(c, f);
  753. X            *s = '\0';
  754. X            return(s - text);
  755. X
  756. X        case '{': case '}':
  757. X            ungetc(c, f);
  758. X            *s = '\0';
  759. X            return(s - text);
  760. X
  761. X        case '[':
  762. X            /* sets may contain embedded white space */
  763. X            if (s + 1 < &text[PROFILE_MAX_TEXT]) {
  764. X                *s++ = '[';
  765. X                if ((c = getc(f)) != EOF)
  766. X                *s++ = c;
  767. X            }
  768. X            while ((c = getc(f)) != EOF) {
  769. X                if (s < &text[PROFILE_MAX_TEXT])
  770. X                    *s++ = c;
  771. X                if (c == ']')
  772. X                    break;
  773. X            }
  774. X            continue;
  775. X
  776. X        case '\\':
  777. X            c = getc(f);
  778. X            if (c == '\n') {
  779. X                if (s > text) {
  780. X                    *s = '\0';
  781. X                    return(s - text);
  782. X                }
  783. X                continue;    /* just like a blank */
  784. X            }
  785. X            ungetc(c, f);
  786. X            if (s < &text[PROFILE_MAX_TEXT])
  787. X                *s++ = '\\';
  788. X            continue;
  789. X
  790. X        default:
  791. X            if (s < &text[PROFILE_MAX_TEXT])
  792. X                *s++ = c;
  793. X            continue;
  794. X        }
  795. X    *s = '\0';
  796. X    return(s - text);
  797. X}
  798. X
  799. X/* Returns non-zero on end of line and zero otherwise. */
  800. Xstatic int get_end_of_line (f)
  801. XFILE *f;
  802. X{
  803. X    int c;
  804. X
  805. X    if ((c = getc(f)) == '\n')
  806. X        return(1);
  807. X    ungetc(c, f);
  808. X    return(0);
  809. X}
  810. X
  811. X/* Returns non-zero on seeing `{' and zero otherwise. */
  812. Xstatic int get_open_bindings (f)
  813. XFILE *f;
  814. X{
  815. X    int c;
  816. X
  817. X    if ((c = getc(f)) == '{')
  818. X        return(1);
  819. X    ungetc(c, f);
  820. X    return(0);
  821. X}
  822. X
  823. X/* Returns non-zero on seeing `}' and zero otherwise. */ 
  824. Xstatic int get_close_bindings (f)
  825. XFILE *f;
  826. X{
  827. X    int c;
  828. X
  829. X    if ((c = getc(f)) == '}')
  830. X        return(1);
  831. X    ungetc(c, f);
  832. X    return(0);
  833. X}
  834. X
  835. X/* Reads a string literal returning the length of the literal text in characters */
  836. Xstatic int get_string (f, text)
  837. XFILE *f;
  838. Xchar *text;
  839. X{
  840. X    register int c;
  841. X    char *s = text;
  842. X
  843. X    /* the first double quote is guaranteed */
  844. X    *s++ = getc(f);
  845. X    while ((c = getc(f)) != EOF)
  846. X        switch (c) {
  847. X        case '\\':
  848. X            if (s < &text[PROFILE_MAX_TEXT])
  849. X                *s++ = c;
  850. X            c = getc(f);
  851. X            if (c == EOF)
  852. X                return(s - text);
  853. X            else if (c == '\n') {
  854. X                ungetc(c, f);
  855. X                return(s - text);
  856. X            } else if (s < &text[PROFILE_MAX_TEXT])
  857. X                *s++ = c;
  858. X            continue;
  859. X
  860. X        case '"':
  861. X            if (s < &text[PROFILE_MAX_TEXT])
  862. X                *s++ = c;
  863. X            *s = '\0';
  864. X            return(s - text);
  865. X
  866. X        case '\n':
  867. X            ungetc(c, f);
  868. X            *s = '\0';
  869. X            return(s - text);
  870. X
  871. X        default:
  872. X            if (s < &text[PROFILE_MAX_TEXT])
  873. X                *s++ = c;
  874. X            continue;
  875. X        }
  876. X    *s = '\0';
  877. X    return(s - text);
  878. X}
  879. X
  880. X/* Reads a character literal returning the length of the literal text in characters. */
  881. Xstatic int get_character (f, text)
  882. XFILE *f;
  883. Xchar *text;
  884. X{
  885. X    register int c;
  886. X    char *s = text;
  887. X
  888. X    /* the first single quote is guaranteed */
  889. X    *s++ = getc(f);
  890. X    while ((c = getc(f)) != EOF)
  891. X        switch (c) {
  892. X        case '\\':
  893. X            if (s < &text[PROFILE_MAX_TEXT])
  894. X                *s++ = c;
  895. X            c = getc(f);
  896. X            if (c == EOF)
  897. X                return(s - text);
  898. X            else if (c == '\n') {
  899. X                ungetc(c, f);
  900. X                return(s - text);
  901. X            } else if (s < &text[PROFILE_MAX_TEXT])
  902. X                *s++ = c;
  903. X            continue;
  904. X        case '\'':
  905. X            if (s < &text[PROFILE_MAX_TEXT])
  906. X                *s++ = c;
  907. X            *s = '\0';
  908. X            return(s - text);
  909. X        case '\n':
  910. X            ungetc(c, f);
  911. X            *s = '\0';
  912. X            return(s - text);
  913. X        default:
  914. X            if (s < &text[PROFILE_MAX_TEXT])
  915. X                *s++ = c;
  916. X            continue;
  917. X        }
  918. X    *s = '\0';
  919. X    return(s - text);
  920. X}
  921. X
  922. X/* all regular expressions below are in lex notation */
  923. X
  924. X/* returns non-zero iff -?[0-9]+ matches */
  925. Xstatic int is_integer (s)
  926. Xchar *s;
  927. X{
  928. X    char *x;
  929. X
  930. X    /* -? */
  931. X    if (*s == '-')
  932. X        s++;
  933. X    /* [0-9]+ */
  934. X    for (x = s; isdigit(*s); s++)
  935. X        continue;
  936. X    return(s > x && !*s);
  937. X}
  938. X
  939. X/* returns non-zero iff 0[oO][0-7]+ matches */
  940. Xstatic int is_octal (s)
  941. Xchar *s;
  942. X{
  943. X    char *x;
  944. X
  945. X    /* 0 */
  946. X    if (*s == '0')
  947. X        s++;
  948. X    else
  949. X        return(0);
  950. X    /* [oO] */
  951. X    if (*s == 'o' || *s == 'O')
  952. X        s++;
  953. X    else
  954. X        return(0);
  955. X    /* [0-7]+ */
  956. X    for (x = s; isoctal(*s); s++)
  957. X        continue;
  958. X    return(s > x && !*s);
  959. X}
  960. X
  961. X/* returns non-zero iff 0[xX][0-9a-fA-F]+ matches */
  962. Xstatic int is_hex (s)
  963. Xchar *s;
  964. X{
  965. X    char *x;
  966. X
  967. X    /* 0 */
  968. X    if (*s == '0')
  969. X        s++;
  970. X    else
  971. X        return(0);
  972. X    /* [xX] */
  973. X    if (*s == 'x' || *s == 'X')
  974. X        s++;
  975. X    else
  976. X        return(0);
  977. X    /* [0-9a-fA-F]+ */
  978. X    for (x = s; ishex(*s); s++)
  979. X        continue;
  980. X    return(s > x && !*s);
  981. X}
  982. X
  983. X/* returns non-zero iff [eE][-+]?[0-9]+ matches */
  984. Xstatic int is_exponent (s)
  985. Xchar *s;
  986. X{
  987. X    char *x;
  988. X
  989. X    /* [eE] */
  990. X    if (*s == 'e' || *s == 'E')
  991. X        s++;
  992. X    else
  993. X        return(0);
  994. X    /* [-+]? */
  995. X    if (*s == '-' || *s == '+')
  996. X        s++;
  997. X    /* [0-9]+ */
  998. X    for (x = s; isdigit(*s); s++)
  999. X        continue;
  1000. X    return(s > x && !*s);
  1001. X}
  1002. X
  1003. Xstatic int is_float (s)
  1004. Xchar *s;
  1005. X{
  1006. X    return(is_integer_part_float(s) ||
  1007. X           is_fractional_part_float(s) ||
  1008. X           is_power_float(s));
  1009. X}
  1010. X
  1011. X/* returns non-zero iff -?[0-9]+"."[0-9]*({exponent})? matches */
  1012. Xstatic int is_integer_part_float (s)
  1013. Xchar *s;
  1014. X{
  1015. X    char *x;
  1016. X
  1017. X    /* -? */
  1018. X    if (*s == '-')
  1019. X        s++;
  1020. X    /* [0-9]+"." */
  1021. X    for (x = s; isdigit(*s); s++)
  1022. X        continue;
  1023. X    if (x == s || *s != '.')
  1024. X        return(0);
  1025. X    /* [0-9]* */
  1026. X    for (s++; isdigit(*s); s++)
  1027. X        continue;
  1028. X    /* ({exponent})? */
  1029. X    return(*s ? is_exponent(s) : 1);
  1030. X}
  1031. X
  1032. X/* returns non-zero iff -?"."[0-9]+({exponent})? matches */
  1033. Xstatic int is_fractional_part_float (s)
  1034. Xchar *s;
  1035. X{
  1036. X    char *x;
  1037. X
  1038. X    /* -? */
  1039. X    if (*s == '-')
  1040. X        s++;
  1041. X    /* "." */
  1042. X    if (*s == '.')
  1043. X        s++;
  1044. X    else
  1045. X        return(0);
  1046. X    /* [0-9]+({exponent})? */
  1047. X    for (x = s; isdigit(*s); s++)
  1048. X        continue;
  1049. X    return(s > x ? !*s || is_exponent(s) : 0);
  1050. X}
  1051. X
  1052. X/* returns non-zero iff -?[0-9]+{exponent} matches */
  1053. Xstatic int is_power_float (s)
  1054. Xchar *s;
  1055. X{
  1056. X    char *x;
  1057. X
  1058. X    /* -? */
  1059. X    if (*s == '-')
  1060. X        s++;
  1061. X    /* [0-9]+{exponent} */
  1062. X    for (x = s; isdigit(*s); s++)
  1063. X        continue;
  1064. X    return(s > x ? is_exponent(s) : 0);
  1065. X}
  1066. X
  1067. X/* returns non-zero iff '[^^\]' | '\^.' | '\\\\' | '\\'' | '\[0-7]{1-3}' matches */
  1068. Xstatic int is_character (s)
  1069. Xchar *s;
  1070. X{
  1071. X    char *x;
  1072. X
  1073. X    if (isprime(*s))
  1074. X        s++;
  1075. X    else
  1076. X        return(0);
  1077. X    if (isbackslash(*s)) {
  1078. X        s++;
  1079. X        if ((isbackslash(s[0]) || isprime(s[0]) || !isdigit(s[0])) &&
  1080. X            isprime(s[1]) && !s[2])
  1081. X            return(1);
  1082. X        for (x = s; isoctal(*s); s++)
  1083. X            continue;
  1084. X        return(x < s && s < (x+4) && isprime(s[0]) && !s[1]);
  1085. X    } else if (iscaret(*s))
  1086. X        s++;
  1087. X    return(isprint(s[0]) && isprime(s[1]) && !s[2]);
  1088. X}
  1089. X
  1090. X/* returns non-zero iff s is a string constant */
  1091. Xstatic int is_string (s)
  1092. Xchar *s;
  1093. X{
  1094. X    char *x;
  1095. X
  1096. X    if (*s != '"')
  1097. X        return(0);
  1098. X    for (s++; *s; s++) {
  1099. X        if (*s == '"')
  1100. X            return(!*++s);    /* quote must be followed by null */
  1101. X        if (isbackslash(*s) || iscaret(*s)) {
  1102. X            if (*++s)
  1103. X                continue;    /* legal escape */
  1104. X            return(0);    /* null follows \ or ^ */
  1105. X        }
  1106. X    }
  1107. X    return(0);
  1108. X}
  1109. X
  1110. X/*
  1111. X * read an entire profile, making a bidirectional
  1112. X * circularly linked list
  1113. X * returns pointer to the first stanza or NULL on error
  1114. X */
  1115. XPROFILE_STANZA *profile_read_profile(f)
  1116. XFILE *f;
  1117. X{
  1118. X    PROFILE_STANZA *head = NULL;
  1119. X    PROFILE_STANZA *tail = NULL;
  1120. X    PROFILE_STANZA *x = NULL;
  1121. X
  1122. X    while ((x = profile_read_stanza(f)) != NULL) {
  1123. X        if (head == NULL)
  1124. X            head = tail = x;
  1125. X        else {
  1126. X            tail->next = x; 
  1127. X            x->previous = tail;
  1128. X            tail = x;
  1129. X        }
  1130. X    }
  1131. X    if (head != NULL) { 
  1132. X        tail->next = head;
  1133. X        head->previous = tail;
  1134. X    }
  1135. X    return(head);
  1136. X}
  1137. !FaR!OuT!
  1138. if [ ! -d libprofile ]
  1139. then
  1140.     mkdir libprofile
  1141.     echo mkdir libprofile
  1142. fi
  1143. echo x - libprofile/space.c
  1144. sed -e 's/^X//' > libprofile/space.c << '!FaR!OuT!'
  1145. Xstatic char *trwsccs = "@(#)space.c    1.1 (TRW) 1/14/86";
  1146. X#include "profile.h"
  1147. X
  1148. Xextern char *calloc();
  1149. X
  1150. XPROFILE_STANZA *profile_stanza_space ()
  1151. X{
  1152. X    return((PROFILE_STANZA *)calloc(1, sizeof(PROFILE_STANZA)));
  1153. X}
  1154. X
  1155. XPROFILE_MARKER *profile_marker_space (n)
  1156. Xint n;
  1157. X{
  1158. X    char *space;
  1159. X    PROFILE_MARKER *m = (PROFILE_MARKER *)0;
  1160. X
  1161. X    if (space = calloc(1, sizeof(PROFILE_MARKER) + n + 1)) {
  1162. X        m = (PROFILE_MARKER *)space;
  1163. X        m->text = space + sizeof(PROFILE_MARKER);
  1164. X    }
  1165. X    return(m);
  1166. X}
  1167. X
  1168. XPROFILE_BINDING *profile_binding_space (n)
  1169. Xint n;        /* length of binding name in characters */
  1170. X{
  1171. X    char *space;
  1172. X    PROFILE_BINDING *b = (PROFILE_BINDING *)0;
  1173. X
  1174. X    if (space = calloc(1, sizeof(PROFILE_BINDING) + n + 1)) {
  1175. X        b = (PROFILE_BINDING *)space;
  1176. X        b->name = space + sizeof(PROFILE_BINDING);
  1177. X    }
  1178. X    return(b);
  1179. X}
  1180. X
  1181. XPROFILE_VALUE *profile_value_space (n)
  1182. Xint n;
  1183. X{
  1184. X    char *space;
  1185. X    PROFILE_VALUE *v = (PROFILE_VALUE *)0;
  1186. X
  1187. X    if (n > 0) {
  1188. X        if (space = calloc(1, sizeof(PROFILE_VALUE) + n + 1)) {
  1189. X            v = (PROFILE_VALUE *)space;
  1190. X            v->value.s = space + sizeof(PROFILE_VALUE);
  1191. X        }
  1192. X    } else
  1193. X        v = (PROFILE_VALUE *)calloc(1, sizeof(PROFILE_VALUE));
  1194. X    return(v);
  1195. X}
  1196. !FaR!OuT!
  1197. if [ ! -d libprofile ]
  1198. then
  1199.     mkdir libprofile
  1200.     echo mkdir libprofile
  1201. fi
  1202. echo x - libprofile/write.c
  1203. sed -e 's/^X//' > libprofile/write.c << '!FaR!OuT!'
  1204. Xstatic char *trwsccs = "@(#)write.c    1.1 (TRW) 1/14/86";
  1205. X#include <stdio.h>
  1206. X#include <ctype.h>
  1207. X#include "profile.h"
  1208. X
  1209. Xprofile_write_stanza (f, s)
  1210. XFILE *f;
  1211. XPROFILE_STANZA *s;
  1212. X{
  1213. X    write_markers(f, s->marker);
  1214. X    fprintf(f, "{\n");
  1215. X    write_bindings(f, s->binding);
  1216. X    fprintf(f, "}\n");
  1217. X}
  1218. X
  1219. Xstatic write_markers (f, m)
  1220. XFILE *f;
  1221. XPROFILE_MARKER *m;
  1222. X{
  1223. X    for (; m; m = m->next)
  1224. X        fprintf(f, "%s\n", m->text);
  1225. X}
  1226. X
  1227. Xstatic write_bindings (f, b)
  1228. XFILE *f;
  1229. XPROFILE_BINDING *b;
  1230. X{
  1231. X    while (b) {
  1232. X        fprintf(f, "\t%s", b->name);
  1233. X        write_values(f, b->value);
  1234. X        fputc('\n', f);
  1235. X        b = b->next;
  1236. X    }
  1237. X}
  1238. X
  1239. Xstatic write_values (f, v)
  1240. XFILE *f;
  1241. XPROFILE_VALUE *v;
  1242. X{
  1243. X    char scratch[PROFILE_MAX_TEXT+1];
  1244. X
  1245. X    for (; v; v = v->next)
  1246. X        switch (v->class) {
  1247. X        case PROFILE_INTEGER:
  1248. X            fprintf(f, " %D", v->value.i);
  1249. X            continue;
  1250. X        case PROFILE_FLOAT:
  1251. X            fprintf(f, " %G", v->value.f);
  1252. X            continue;
  1253. X        case PROFILE_STRING:
  1254. X            unparse_string(v->value.s, scratch);
  1255. X            fprintf(f, " \"%s\"", scratch);
  1256. X            continue;
  1257. X        case PROFILE_CHARACTER:
  1258. X            unparse_character(v->value.c, scratch);
  1259. X            fprintf(f, " '%s'", scratch);
  1260. X            continue;
  1261. X        case PROFILE_OCTAL:
  1262. X            fprintf(f, " 0o%O", v->value.i);
  1263. X            continue;
  1264. X        case PROFILE_HEX:
  1265. X            fprintf(f, " 0x%X", v->value.i);
  1266. X            continue;
  1267. X        case PROFILE_OTHER:
  1268. X            fprintf(f, " %s", v->value.s);
  1269. X            continue;
  1270. X        }
  1271. X}
  1272. X
  1273. Xstatic int unparse_string (from, to)
  1274. Xchar *from;
  1275. Xchar *to;
  1276. X{
  1277. X    char *x = to;
  1278. X
  1279. X    for (; *from; from++)
  1280. X        switch (*from) {
  1281. X        case '\b':        /* backspace */
  1282. X            *x++ = '\\';
  1283. X            *x++ = 'b';
  1284. X            continue;
  1285. X        case '\f':        /* formfeed */
  1286. X            *x++ = '\\';
  1287. X            *x++ = 'f';
  1288. X            continue;
  1289. X        case '\n':        /* newline */
  1290. X            *x++ = '\\';
  1291. X            *x++ = 'n';
  1292. X            continue;
  1293. X        case '\r':
  1294. X            *x++ = '\\';
  1295. X            *x++ = 'r';
  1296. X            continue;
  1297. X        case '\t':        /* horizontal tab */
  1298. X            *x++ = '\\';
  1299. X            *x++ = 't';
  1300. X            continue;
  1301. X        case '\\':        /* backslash */
  1302. X            *x++ = '\\';
  1303. X            continue;
  1304. X        case '"':        /* double quote */
  1305. X            *x++ = '\\';
  1306. X            *x++ = '"';
  1307. X            continue;
  1308. X        case '^':
  1309. X            *x++ = '\\';
  1310. X            *x++ = '^';
  1311. X            continue;
  1312. X        default:
  1313. X            if (isascii(*from))
  1314. X                if (iscntrl(*from)) {
  1315. X                    sprintf(x, "^%c", *from == '\177' ? '?' : *from + '@');
  1316. X                    x += 2;
  1317. X                } else
  1318. X                    *x++ = *from;
  1319. X            else {
  1320. X                sprintf(x, "\\%03o", *from);
  1321. X                x += 4;
  1322. X            }
  1323. X            continue;
  1324. X        }
  1325. X    *x = '\0';
  1326. X    return(x - to);
  1327. X}
  1328. X
  1329. Xstatic int unparse_character (from, to)
  1330. Xchar from;
  1331. Xchar *to;
  1332. X{
  1333. X    char *x = to;
  1334. X
  1335. X    switch (from) {
  1336. X    case '\b':        /* backspace */
  1337. X        *x++ = '\\';
  1338. X        *x++ = 'b';
  1339. X        break;
  1340. X    case '\f':        /* formfeed */
  1341. X        *x++ = '\\';
  1342. X        *x++ = 'f';
  1343. X        break;
  1344. X    case '\n':        /* newline */
  1345. X        *x++ = '\\';
  1346. X        *x++ = 'n';
  1347. X        break;
  1348. X    case '\r':
  1349. X        *x++ = '\\';
  1350. X        *x++ = 'r';
  1351. X        break;
  1352. X    case '\t':        /* horizontal tab */
  1353. X        *x++ = '\\';
  1354. X        *x++ = 't';
  1355. X        break;
  1356. X    case '\\':        /* backslash */
  1357. X        *x++ = '\\';
  1358. X        break;
  1359. X    case '\'':        /* single quote */
  1360. X        *x++ = '\\';
  1361. X        *x++ = '\'';
  1362. X        break;
  1363. X    case '^':
  1364. X        *x++ = '\\';
  1365. X        *x++ = '^';
  1366. X        break;
  1367. X    default:
  1368. X        if (isascii(from))
  1369. X            if (iscntrl(from)) {
  1370. X                sprintf(x, "^%c", from == '\177' ? '?' : from + '@');
  1371. X                x += 2;
  1372. X            } else
  1373. X                *x++ = from;
  1374. X        else {
  1375. X            sprintf(x, "\\%03o", from);
  1376. X            x += 4;
  1377. X        }
  1378. X        break;
  1379. X    }
  1380. X    *x = '\0';
  1381. X    return(x - to);
  1382. X}
  1383. X
  1384. X/*
  1385. X * write out a linked list of stanzas
  1386. X */
  1387. Xprofile_write_profile(f, s)
  1388. XFILE *f;
  1389. XPROFILE_STANZA *s;
  1390. X{
  1391. X    PROFILE_STANZA *x;
  1392. X
  1393. X    for (x = s; x != NULL; x = x->next) {
  1394. X        profile_write_stanza(f, x);
  1395. X        if (x->next == s)
  1396. X            break;
  1397. X    }
  1398. X}
  1399. !FaR!OuT!
  1400. if [ ! -d man ]
  1401. then
  1402.     mkdir man
  1403.     echo mkdir man
  1404. fi
  1405. echo x - man/glob.3
  1406. sed -e 's/^X//' > man/glob.3 << '!FaR!OuT!'
  1407. X.\" %W% (TRW) %G%
  1408. X.TH GLOB 3 TRW
  1409. X.UC
  1410. X.SH NAME
  1411. Xglob \- shell style pattern matching
  1412. X.SH SYNOPSIS
  1413. X.nf
  1414. X.B #include <local/glob.h>
  1415. X
  1416. X.B int glob_compile(pattern, buffer)
  1417. X.B char *pattern;
  1418. X.B char *buffer;
  1419. X
  1420. X.B int glob_execute(buffer, s)
  1421. X.B char *buffer;
  1422. X.B char *s;
  1423. X
  1424. X.B int glob_match (pattern, s)
  1425. X.B char *pattern;
  1426. X.B char *s;
  1427. X.fi
  1428. X
  1429. X.B cc 
  1430. X[ flags ] files
  1431. X.B -lglob
  1432. X[ libraries ]
  1433. X.fi
  1434. X.SH DESCRIPTION
  1435. X.I Glob
  1436. Xis a pattern matching facility similar to that of
  1437. X.IR sh (1)
  1438. Xand
  1439. X.IR csh (1).
  1440. X.PP
  1441. XA pattern specifies a set of strings of characters.
  1442. XA member of this set of strings is said to be matched by the pattern.
  1443. X.TP
  1444. X(1)
  1445. XAny character except a special character matches itself.
  1446. XThe special characters are [ * and ?.
  1447. X.TP
  1448. X(2)
  1449. XA ? matches any character.
  1450. X.TP
  1451. X(3)
  1452. XA nonempty string
  1453. X.I s
  1454. Xbracketed
  1455. X.RI [ s ]
  1456. Xmatches any character in
  1457. X.IR s .
  1458. XIn
  1459. X.I s
  1460. X] may only appear as the first letter.
  1461. XA substring
  1462. X.IR a \- b ,
  1463. Xwith
  1464. X.I a
  1465. Xand
  1466. X.I b
  1467. Xin ascending ASCII order,
  1468. Xstands for the inclusive range of ASCII characters.
  1469. X.TP
  1470. X(4)
  1471. XA * matches 0 or more characters.
  1472. X.PP
  1473. X.I Glob_compile
  1474. Xcompiles a
  1475. X.I pattern
  1476. Xinto an internal form suitable for matching,
  1477. Xplacing the result in the character array
  1478. X.IR buffer .
  1479. X.I Buffer
  1480. Xmust be a character array of size
  1481. X.BR GLOB_MAX_PATTERN .
  1482. X.I Glob_compile
  1483. Xreturns 0 if the
  1484. X.I pattern
  1485. Xwas compiled successfully;
  1486. Xotherwise a negative error code is returned.
  1487. X.PP
  1488. X.I Glob_execute
  1489. Xchecks the argument string
  1490. X.I s
  1491. Xagainst the compiled
  1492. X.IR pattern .
  1493. X.I Glob_execute
  1494. Xreturns 1 if the string
  1495. X.I s
  1496. Xmatches the compiled pattern in
  1497. X.IR buffer ,
  1498. X0 if the string
  1499. X.I s
  1500. Xfailed to match the compiled pattern in
  1501. X.IR buffer ,
  1502. Xand a negative error code if the compiled pattern was invalid.
  1503. X.PP
  1504. XThe strings passed to both
  1505. X.I glob_compile
  1506. Xand
  1507. X.I glob_execute
  1508. Xmay have trailing or embedded newline characters;
  1509. Xthey are terminated by nulls.
  1510. X.PP
  1511. X.I Glob_match
  1512. Xcompiles
  1513. X.I pattern
  1514. Xand matches it against the argument string
  1515. X.IR s .
  1516. XIt returns 1 if the string
  1517. X.I s
  1518. Xmatches the pattern;
  1519. X0 if the string
  1520. X.I s
  1521. Xfails to match the pattern
  1522. Xand a negative error code if the pattern was invalid.
  1523. X.SH AUTHOR
  1524. XMichael Gorlick, TRW
  1525. X.SH SEE ALSO
  1526. Xregex(3)
  1527. X.SH DIAGNOSTICS
  1528. XThe following diagnostic codes are provided:
  1529. X.TP
  1530. XGLOB_OK
  1531. Xreturned by
  1532. X.I glob_compile
  1533. Xindicating the pattern compiled successfully;
  1534. X.TP
  1535. XGLOB_PATTERN_TOO_BIG
  1536. Xreturned by
  1537. X.I glob_compile
  1538. Xor
  1539. X.I glob_match
  1540. Xindicating the compiled pattern overflowed the buffer;
  1541. X.TP
  1542. XGLOB_PATTERN_EMPTY
  1543. Xreturned by
  1544. X.I glob_compile
  1545. Xor
  1546. X.I glob_match
  1547. Xindicating the pattern is the empty string;
  1548. X.TP
  1549. XGLOB_BRACKET_MISSING
  1550. Xreturned by
  1551. X.I glob_compile
  1552. Xor
  1553. X.I glob_match
  1554. Xindicating that a set expression
  1555. X.RI [ s ]
  1556. Xis missing the terminating bracket ];
  1557. X.TP
  1558. XGLOB_RANGE_INVERTED
  1559. Xreturned by
  1560. X.I glob_compile
  1561. Xor
  1562. X.I glob_match
  1563. Xindicating a range expression in a set
  1564. Xis inverted, for example [z-a];
  1565. X.TP
  1566. XGLOB_SET_TOO_BIG
  1567. Xreturned by
  1568. X.I glob_compile
  1569. Xor
  1570. X.I glob_match
  1571. Xindicating a compiled set requires more than 127 bytes
  1572. X(a single character consumes 2 bytes and a range consumes 3 bytes);
  1573. X.TP
  1574. XGLOB_EXECUTION_ERROR
  1575. Xreturned by
  1576. X.I glob_execute
  1577. Xor
  1578. X.I glob_match
  1579. Xindicating an internal error.
  1580. !FaR!OuT!
  1581. if [ ! -d man ]
  1582. then
  1583.     mkdir man
  1584.     echo mkdir man
  1585. fi
  1586. echo x - man/index.1
  1587. sed -e 's/^X//' > man/index.1 << '!FaR!OuT!'
  1588. X.\" $Header: index.1,v 1.1 86/06/10 08:25:56 control Exp $
  1589. X.if t .ds LX L\v'-.22m'a\v'.22m'T\h'-.1667m'\v'.22m'E\h'-.125m'\v'-.22m'X
  1590. X.if n .ds LX LaTeX
  1591. X.TH INDEX 1 TRW
  1592. X.UC
  1593. X.SH NAME
  1594. Xindex \- index processor for converting LaTeX idx files
  1595. X.SH ORIGIN
  1596. XTRW
  1597. X.SH SYNOPSIS
  1598. X.B index [ -l ]
  1599. X.B [ -f
  1600. X.I alphabetizefile
  1601. X.B ] [
  1602. X.I file...
  1603. X.B ]
  1604. X.SH DESCRIPTION
  1605. X.I Index
  1606. Xconverts 
  1607. X.I idx 
  1608. Xfiles generated by \*(LX into 
  1609. X.I theindex 
  1610. Xenvironments that can be processed by \*(LX.
  1611. XMultiple files may be given.
  1612. XIf the file is not found, the extension
  1613. X.I idx
  1614. Xis appended and the new file is looked for.
  1615. XIndex files will be created with the extension
  1616. X.I ind.
  1617. XIf no files are given, standard input is read and standard output it written.
  1618. XSubitems and subsubitems can be generated by separating index entries
  1619. Xwith commas.
  1620. XFor example, after running your document
  1621. Xthrough \*(LX you may obtain an index file 
  1622. X.I sample.idx
  1623. Xcontaining entries
  1624. Xthat look like
  1625. X.RS
  1626. X.nf
  1627. X\eindexentry{Reagan}{32}
  1628. X\eindexentry{Reagan}{54}
  1629. X\eindexentry{Reagan,republicans}{54}
  1630. X\eindexentry{Carter}{60}
  1631. X\eindexentry{Reagan,republicans,conventions}{62}
  1632. X.fi
  1633. X.RE
  1634. XAfter running the index file through
  1635. X.I index
  1636. Xa file
  1637. X.I sample.ind 
  1638. Xwill be created that will contain
  1639. X.RS
  1640. X.nf
  1641. X\ebegin{theindex}
  1642. X\eitem Carter 60
  1643. X\eindexspace 
  1644. X\eitem Reagan 32, 54
  1645. X  \esubitem republicans 54
  1646. X    \esubsubitem conventions 62
  1647. X\eend{theindex}
  1648. X.fi
  1649. X.RE
  1650. XThe 
  1651. X.I indexspace 
  1652. Xleaves a little extra vertical space between the entries that start with
  1653. Xa new letter.
  1654. XIf the 
  1655. X.I -l 
  1656. Xoption is given, then a large index letter will precede each entry
  1657. Xthat starts with a new letter.
  1658. X.PP
  1659. X.I Index
  1660. Xreads the file
  1661. X.I .alphabetize
  1662. Xin the home directory if it exists
  1663. Xto determine how to alphabetize an
  1664. X.I idx
  1665. Xfile.
  1666. XThis file contains rules for skipping control sequences, characters, etc
  1667. Xwhen alphabetizing a file.
  1668. XThe format of this file is described in
  1669. X.IR index (5).
  1670. XIf the 
  1671. X.I -f 
  1672. Xoption is given, then another alphabetization file can be given.
  1673. X.PP
  1674. XA dash following an entry indicates the beginning of a range. 
  1675. XThe range is ended by the occurence of the next equivalent entry.
  1676. XFor example, suppose you had a \*(LX file containing
  1677. X.RS
  1678. X.nf
  1679. X\&...and they fought\eindex{fighting-} and wept...
  1680. X.fi
  1681. X.RE
  1682. Xon page 40 and
  1683. X.RS
  1684. X.nf
  1685. X\&...and were still fighting\eindex{fighting} years later...
  1686. X.fi
  1687. X.RE 
  1688. Xon page 42 with no intervening
  1689. X.I \eindex
  1690. Xcommands.
  1691. XThen after running the 
  1692. X.I idx
  1693. Xfile through 
  1694. X.I index,
  1695. Xthe line 
  1696. X.RS
  1697. X.nf
  1698. X\eitem fighting 40--42
  1699. X.fi
  1700. X.RE 
  1701. Xwould be contained in the 
  1702. X.I ind 
  1703. Xfile.
  1704. XWhen ranges are given for subitems and subsubitems, only the last
  1705. Xcomma separated entry should have a dash suffix.
  1706. XDuplicate page numbers are suppressed.
  1707. X.PP
  1708. XIf you wish to insert a comma into your index entry, you will need to 
  1709. Xhide it from the index processor with braces
  1710. Xsince only outer level commas are recognized as item delimeters.
  1711. XFor example,
  1712. X.RS
  1713. X.nf
  1714. X\eindex{Reagan{,} Ronald}
  1715. X.fi
  1716. X.RE
  1717. Xgenerates the index entry for
  1718. X.I Reagan, Ronald.
  1719. X.SH FILES
  1720. X.nf
  1721. X.ta \w'~/.alphabetize  'u
  1722. X~/.alphabetize    Default alphabetization file
  1723. X.fi
  1724. X.SH AUTHOR
  1725. XScott Simpson
  1726. X.SH SEE ALSO
  1727. Xprofile(3), index(5), profile(5)
  1728. X.SH DIAGNOSTICS
  1729. XComplains about illegal values in bindings in alphabetization file.
  1730. !FaR!OuT!
  1731. if [ ! -d man ]
  1732. then
  1733.     mkdir man
  1734.     echo mkdir man
  1735. fi
  1736. echo x - man/index.5
  1737. sed -e 's/^X//' > man/index.5 << '!FaR!OuT!'
  1738. X.\" $Header
  1739. X.if t .ds LX L\v'-.22m'a\v'.22m'T\h'-.1667m'\v'.22m'E\h'-.125m'\v'-.22m'X
  1740. X.if n .ds LX LaTeX
  1741. X.TH INDEX 5 TRW
  1742. X.UC
  1743. X.SH NAME
  1744. Xindex \- format of alphabetization stanza for LaTeX index processor
  1745. X.SH ORIGIN
  1746. XTRW
  1747. X.SH SYNOPSIS
  1748. X~/.alphabetize
  1749. X.SH DESCRIPTION
  1750. XThe \*(LX index processor
  1751. X.IR index (1)
  1752. Xreads the file
  1753. X.I .alphabetize
  1754. Xfile in the home directory to determine
  1755. Xhow to sort index entries.
  1756. XThis file is in 
  1757. X.IR profile (5)
  1758. Xformat and consists of a stanza containing bindings.
  1759. XThese bindings consist of key/value pairs.
  1760. XThere may be multiple values for each key.
  1761. X.PP
  1762. XThe stanza contained in the 
  1763. X.I .alphabetize 
  1764. Xfile should contain one stanza with the marker 
  1765. X.I alphabetize.
  1766. XThis stanza may contain three keys: 
  1767. X.I skipchars,
  1768. X.I mapctrlsequence 
  1769. Xand 
  1770. X.I mapindexentry.
  1771. X.PP
  1772. X.I Skipchars
  1773. Xis a list of characters to ignore when alphabetizing index entries.
  1774. X.PP
  1775. X.I Mapctrlsequence
  1776. Xis a list of pairs of values.
  1777. XThe odd numbered value 
  1778. X.I n
  1779. X(a control sequence)
  1780. Xmaps into the even value
  1781. X.I n+1
  1782. X(any text).
  1783. XThe leading backslash may 
  1784. Xbe omitted for the odd control sequence strings.
  1785. X.PP
  1786. X.I Mapindexentry
  1787. Xis a list of index entries to match exactly.
  1788. XThe odd numbered value
  1789. X.I n
  1790. X(an index entry) maps into the even value
  1791. X.I n+1
  1792. X(any text).
  1793. XThe backslashes
  1794. Xmay not be omitted here.
  1795. X.SH EXAMPLES
  1796. XHere is an example stanza to help clarify some ideas.
  1797. X.RS
  1798. X.nf
  1799. X.ta \w'    mapctrlsequence     'u
  1800. Xalphabetize
  1801. X{
  1802. X    skipchars        '{' '}' '$' '\e^' '\e'' '`' '_' '"'
  1803. X    mapctrlsequence    "\e\etrwlogo" "TRW" \e
  1804. X            "LaTeX" "LaTeX"
  1805. X    mapindexentry    "\e\everb|\e\e\e\e|" "\e\e" \e
  1806. X            "\e\everb|\e\e\e"|" "\e""
  1807. X}
  1808. X.fi
  1809. X.RE
  1810. XWhen alphabetizing the index file, the characters {, }, $, ^, ', `, _,
  1811. Xand " will be ignored.
  1812. X.IR Profile (5)
  1813. Xrequires escaping the ^, ' and \e.
  1814. X.PP
  1815. XThe control word
  1816. X.I \etrwlogo
  1817. Xwill be treated as the string
  1818. X.I TRW
  1819. Xwherever it occurs in an index entry
  1820. Xand the control word
  1821. X.I \eLaTeX
  1822. Xwill be treated as 
  1823. X.I LaTeX
  1824. Xwherever it occurs in an index entry.
  1825. XNote that the leading backslash in the third value (i.e.,
  1826. X.IR \eLaTeX )
  1827. Xcan be omitted without ill effect.
  1828. XNormally, control words and control symbols are removed when alphabetizing.
  1829. X.PP
  1830. XThe index entries
  1831. X.I \everb|\e\e|
  1832. Xand
  1833. X\fI\everb|\e"|\fR
  1834. Xwill be treated as \e and " when alphabetizing, respectively.
  1835. X.PP
  1836. XHere is one last example illustrating the sorting rules.
  1837. XSuppose we have the stanza
  1838. X.RS
  1839. X.nf
  1840. X.ta \w'    mapctrlsequence     'u
  1841. Xalphabetize
  1842. X{
  1843. X    skipchars        '{' '}'
  1844. X    mapctrlsequence    "\e\ehello" "salutation"
  1845. X    mapindexentry    "{\e\ela de da}" "z"
  1846. X}
  1847. X.fi
  1848. X.RE
  1849. Xand we have the
  1850. X.I \eindex
  1851. Xcommands
  1852. X.RS
  1853. X.nf
  1854. X\eindex{{\ebf Orca!} kills}
  1855. X\eindex{say,{\ela de da}}
  1856. X\eindex{say,{\ehello} there}
  1857. X\eindex{say,mazzard}
  1858. X\eindex{{\ela de da} de da}
  1859. X\eindex{{\eit Wolfman} Jack}
  1860. X.fi
  1861. X.RE
  1862. Xsprinkled throughout the document.
  1863. X\*(LX may generate the following 
  1864. X.I idx
  1865. Xfile
  1866. X.RS
  1867. X.nf
  1868. X\eindexentry{{\ebf Orca!} kills}{5}
  1869. X\eindexentry{say,{\ela de da}}{10}
  1870. X\eindexentry{say,{\ehello} there}{15}
  1871. X\eindexentry{say,mazzard}{20}
  1872. X\eindexentry{{\ela de da} de da}{25}
  1873. X\eindexentry{{\eit Wolfman} Jack}{30}
  1874. X.fi
  1875. X.RE
  1876. XAfter running through
  1877. X.I index
  1878. Xwe obtain the 
  1879. X.I ind
  1880. Xfile
  1881. X.RS
  1882. X.nf
  1883. X\ebegin{theindex}
  1884. X\eitem {\ela de da} de da 25
  1885. X\eindexspace
  1886. X\eitem {\ebf Orca!} kills 5
  1887. X\eindexspace
  1888. X\eitem say
  1889. X  \esubitem mazzard 20
  1890. X  \esubitem {\ehello} there 15
  1891. X  \esubitem {\ela de da} 10
  1892. X\eindexspace
  1893. X\eitem {\eit Wolfman} Jack 30
  1894. X\eend{theindex}
  1895. X.fi
  1896. X.RE
  1897. XThe entries are logically sorted using the strings
  1898. X.RS
  1899. X.nf
  1900. Xdedadeda
  1901. XOrca!kills
  1902. Xsay
  1903. X  mazzard
  1904. X  salutationthere
  1905. X  z
  1906. XWolfmanJack
  1907. X.fi
  1908. X.RE
  1909. XNote that the 
  1910. X.I mapindexentry
  1911. Xmust match everything between the commas and braces while the 
  1912. X.I mapctrlsequence
  1913. Xmatches control sequences anywhere within the index entry.
  1914. X.SH COMMENTS
  1915. XThe 
  1916. X.I mapindexentry 
  1917. Xentries are examined first and must completely match an index entry.
  1918. XIf they match, no other alphabetizing substitution takes place.
  1919. X.br
  1920. XUpper and lower case letters are equivalent when sorting.
  1921. XUpper case alphabetics are converted to lower case; consequently,
  1922. Xmost non-alphabetic characters precede the alphabetic characters
  1923. Xin the ASCII collating sequence.
  1924. XThe exception are the characters {, |, } and ~.
  1925. X.br
  1926. XBlanks are ignored when sorting.
  1927. X.br
  1928. XAfter control sequences are expanded into their logical sort string,
  1929. Xthey are not scanned for
  1930. X.I skipchars.
  1931. X.br
  1932. XLowercase roman numerals are recognized when the \epagestyle is roman.
  1933. XThey always precede their arabic counterparts.
  1934. XUppercase roman numerals are not recognized.
  1935. X.SH FILES
  1936. X.nf
  1937. X.ta \w'~/.alphabetize   'u
  1938. X~/.alphabetize    alphabetization file
  1939. X.fi
  1940. X.SH AUTHOR
  1941. XScott Simpson
  1942. X.SH SEE ALSO
  1943. Xindex(1), profile(3), profile(5), ascii(7)
  1944. X.SH BUGS
  1945. XThis manual page is confusing.
  1946. !FaR!OuT!
  1947. if [ ! -d man ]
  1948. then
  1949.     mkdir man
  1950.     echo mkdir man
  1951. fi
  1952. echo x - man/profile.3
  1953. sed -e 's/^X//' > man/profile.3 << '!FaR!OuT!'
  1954. X.\" %W% (TRW) %G%
  1955. X.TH PROFILE 3 TRW
  1956. X.UC 4
  1957. X.SH NAME
  1958. Xprofile \- read/write configuration files
  1959. X.SH SYNOPSIS
  1960. X.nf
  1961. X.B #include <stdio.h>
  1962. X.B #include <local/profile.h>
  1963. X
  1964. X.B PROFILE_STANZA *profile_read_stanza(f)
  1965. X.B FILE *f;
  1966. X
  1967. X.B PROFILE_STANZA *profile_read_profile(f)
  1968. X.B FILE *f;
  1969. X
  1970. X.B profile_write_stanza(f, s)
  1971. X.B FILE *f;
  1972. X.B PROFILE_STANZA *s;
  1973. X
  1974. X.B profile_write_profile(f, s)
  1975. X.B FILE *f;
  1976. X.B PROFILE_STANZA *s;
  1977. X
  1978. X.B profile_free_stanza(s)
  1979. X.B PROFILE_STANZA *s;
  1980. X
  1981. X.B PROFILE_MARKER *profile_has_marker(s, m)
  1982. X.B PROFILE_STANZA *s;
  1983. X.B char *m;
  1984. X
  1985. X.B PROFILE_STANZA *profile_has_stanza(s, marker)
  1986. X.B PROFILE_STANZA *s;
  1987. X.B char *marker[];
  1988. X
  1989. X.B PROFILE_BINDING *profile_has_binding(s, b)
  1990. X.B PROFILE_STANZA *s;
  1991. X.B char *b;
  1992. X
  1993. X.B PROFILE_STANZA *profile_stanza_space()
  1994. X
  1995. X.B PROFILE_MARKER *profile_marker_space(n)
  1996. X.B int n;
  1997. X
  1998. X.B PROFILE_BINDING *profile_binding_space(n)
  1999. X.B int n;
  2000. X
  2001. X.B PROFILE_VALUE *profile_value_space(n)
  2002. X.B int n;
  2003. X.fi
  2004. X.SH DESCRIPTION
  2005. X.I Profile_read_stanza
  2006. Xreads a single stanza from a configuration file returning
  2007. Xa pointer to the stanza if successful and NULL on error or end of file.
  2008. XA stanza is defined as:
  2009. X.nf
  2010. X.ta 1i +\w'typedef 'u
  2011. X
  2012. X    typedef struct PROFILE_STANZA {
  2013. X        PROFILE_MARKER *marker;
  2014. X        PROFILE_BINDING *binding;
  2015. X        struct PROFILE_STANZA *previous;
  2016. X        struct PROFILE_STANZA *next;
  2017. X    } PROFILE_STANZA;
  2018. X.fi
  2019. X.PP
  2020. X.I Marker
  2021. Xand
  2022. X.I binding
  2023. Xpoint to linked lists of markers and bindings respectively.
  2024. XIf
  2025. X.I marker
  2026. Xis
  2027. X.B NULL
  2028. Xthe stanza has no markers.
  2029. XIf
  2030. X.I binding
  2031. Xis
  2032. X.B NULL
  2033. Xthe stanza has no bindings.
  2034. X.I Previous
  2035. Xand
  2036. X.I next
  2037. Xare ignored and may be used to doubly link successive stanzas together.
  2038. X.DT
  2039. X.PP
  2040. XA marker is defined as:
  2041. X.nf
  2042. X.ta 1i +\w'typedef 'u
  2043. X
  2044. X    typedef struct PROFILE_MARKER {
  2045. X        char *text;
  2046. X        struct PROFILE_MARKER *previous;
  2047. X        struct PROFILE_MARKER *next;
  2048. X    } PROFILE_MARKER;
  2049. X.fi
  2050. X.DT
  2051. X.PP
  2052. X.I Text
  2053. Xis a string containing the literal text of the marker
  2054. Xand is always nonempty.
  2055. X.IR Previous " (" next )
  2056. Xis a pointer to the previous (next) marker in the sequence.
  2057. XIn the first (last) marker
  2058. X.IR previous " (" next )
  2059. Xis
  2060. X.BR NULL .
  2061. X.PP
  2062. XA binding is defined as:
  2063. X.nf
  2064. X.ta 1i +\w'typedef 'u
  2065. X
  2066. X    typedef struct PROFILE_BINDING {
  2067. X        char *name;
  2068. X        PROFILE_VALUE *value;
  2069. X        struct PROFILE_BINDING *previous;
  2070. X        struct PROFILE_BINDING *next;
  2071. X    } PROFILE_BINDING;
  2072. X.fi
  2073. X.DT
  2074. X.PP
  2075. X.I Name
  2076. Xis the literal text of the name of the binding and is always nonempty.
  2077. X.I Value
  2078. Xis a pointer to the list of values associated with the name.
  2079. XIf
  2080. X.I value
  2081. Xis
  2082. X.B NULL
  2083. Xthen the binding consists solely of a name with no associated value.
  2084. X.IR Previous " (" next )
  2085. Xpoints to the previous (next) binding in the sequence.
  2086. XIn the first (last) binding
  2087. X.IR previous " (" next )
  2088. Xis
  2089. X.BR NULL .
  2090. X.PP
  2091. XA value is defined as:
  2092. X.nf
  2093. X.ta 1i +\w'typedef 'u +\w'union { 'u
  2094. X
  2095. X    typedef struct PROFILE_VALUE {
  2096. X        char class;
  2097. X        union {
  2098. X            long int i;
  2099. X            double f;
  2100. X            char c;
  2101. X            char *s;
  2102. X        } value;
  2103. X        struct PROFILE_VALUE *previous;
  2104. X        struct PROFILE_VALUE *next;
  2105. X    } PROFILE_VALUE;
  2106. X.fi
  2107. X.DT
  2108. X.PP
  2109. X.I Class
  2110. Xis always one of:
  2111. X.TP
  2112. XPROFILE_CHARACTER
  2113. Xthe value is a character constant contained in
  2114. X.IR c .
  2115. X.TP
  2116. XPROFILE_HEX
  2117. Xthe value is a hex constant contained in
  2118. X.IR i .
  2119. X.TP
  2120. XPROFILE_INTEGER
  2121. Xthe value is an integer constant contained in
  2122. X.IR i .
  2123. X.TP
  2124. XPROFILE_FLOAT
  2125. Xthe value is a real constant contained in
  2126. X.IR f .
  2127. X.TP
  2128. XPROFILE_OCTAL
  2129. Xthe value is an octal constant contained in
  2130. X.IR i .
  2131. X.TP
  2132. XPROFILE_STRING
  2133. Xthe value is a string constant contained in
  2134. X.IR s .
  2135. X.TP
  2136. XPROFILE_OTHER
  2137. Xthe value is not recognizably
  2138. Xcharacter,
  2139. Xhex,
  2140. Xinteger,
  2141. Xfloat,
  2142. Xoctal
  2143. Xor string.
  2144. XThe literal text is contained in
  2145. X.IR s .
  2146. X.PP
  2147. X.IR Previous " (" next )
  2148. Xpoints to the previous (next) value in the sequence.
  2149. XIn the first (last) value
  2150. X.IR previous " (" next )
  2151. Xis
  2152. X.BR NULL .
  2153. X.PP
  2154. X.I Profile_read_profile
  2155. Xreads an entire configuration file and builds a bi-directional, 
  2156. Xcircularly linked list of stanzas using the 
  2157. X.I previous
  2158. Xand 
  2159. X.I next
  2160. Xpointers.
  2161. XThe value returned is a pointer to the first stanza in the list.
  2162. X.PP
  2163. X.I Profile_write_stanza
  2164. Xwrites a stanza in a canonical form suitable for input by
  2165. X.IR profile_read_stanza .
  2166. XMarkers are output one to a line.
  2167. XEach binding is indented by a single tab.
  2168. XNames and values are separated, one from the other,
  2169. Xby a single blank.
  2170. X.PP
  2171. X.I Profile_write_profile
  2172. Xwrites all the stanzas in a linked list by applying
  2173. X.I profile_write_stanza
  2174. Xto each stanza in the list.
  2175. XThe list need not be doubly linked.
  2176. X.PP
  2177. X.I Profile_free_stanza
  2178. Xfrees all storage associated with a stanza.
  2179. X.PP
  2180. X.I Profile_has_marker
  2181. Xsearches the marker list of a stanza for a match to the given marker,
  2182. X.IR m .
  2183. XA pointer to the marker is returned on success and
  2184. X.B NULL
  2185. Xon failure.
  2186. X.PP
  2187. X.I Profile_has_stanza
  2188. Xsearches a linked list of stanzas for a stanza that has all the
  2189. Xmarkers in
  2190. X.I marker.
  2191. X.I Marker 
  2192. Xmust be terminated by a null entry.
  2193. X.PP
  2194. X.I Profile_has_binding
  2195. Xsearches the binding list of a stanza
  2196. Xfor a binding with a match to the given name.
  2197. XA pointer to the binding is returned on success and
  2198. X.B NULL
  2199. Xon failure.
  2200. X.PP
  2201. XThe following routines are useful for constructing stanzas on the fly.
  2202. X.I Profile_stanza_space
  2203. Xallocates storage for a stanza.
  2204. X.I Profile_marker_space
  2205. Xallocates storage for a marker including sufficient space for
  2206. X.I n
  2207. Xcharacters of text plus a terminating null byte.
  2208. X.I Profile_binding_space
  2209. Xallocates storage for a binding including sufficient space for
  2210. X.I n
  2211. Xcharacters of name text plus a terminating null byte.
  2212. X.I Profile_value_space
  2213. Xallocates storage for a value.
  2214. XIf
  2215. X.I n
  2216. Xis positive and non-zero the component
  2217. X.IR value . s
  2218. Xis initialized as a
  2219. X.IR n +1
  2220. Xcharacter array.
  2221. XAll of the above routines return a pointer on success and
  2222. X.B NULL
  2223. Xon failure.
  2224. XAll storage is zero filled.
  2225. XThe routine
  2226. X.IR free (3)
  2227. Xmay be safely used to release storage allocated by these routines.
  2228. X.SH AUTHOR
  2229. XMichael Gorlick, TRW
  2230. X.SH SEE ALSO
  2231. Xmalloc(3), profile(5)
  2232. !FaR!OuT!
  2233. if [ ! -d man ]
  2234. then
  2235.     mkdir man
  2236.     echo mkdir man
  2237. fi
  2238. echo x - man/profile.5
  2239. sed -e 's/^X//' > man/profile.5 << '!FaR!OuT!'
  2240. X.\" @(#)profile.5    1.1 (TRW) 6/11/84
  2241. X.TH PROFILE 5 TRW
  2242. X.UC 4
  2243. X.SH NAME
  2244. Xprofile \- configuration file format
  2245. X.SH SYNOPSIS
  2246. X.B #include <local/profile.h>
  2247. X.SH DESCRIPTION
  2248. X.I Profile
  2249. Xis a general purpose configuration file facility.
  2250. X.PP
  2251. XEach profile is an ASCII file containing a sequence of one or more
  2252. X.IR stanzas .
  2253. XEach stanza in turn consists of a sequence of
  2254. X.I markers
  2255. Xfollowed by a sequence of
  2256. X.IR bindings .
  2257. XThe characters `{' (left brace) and `}' (right brace)
  2258. Xdelimit the beginning and end respectively of the stanza bindings.
  2259. XEach binding consists of a name
  2260. Xfollowed by an optional sequence of values. 
  2261. X.SH MARKERS
  2262. XMarkers are arbitrary patterns in the style of
  2263. X.IR glob (3)
  2264. Xdelimited by white space.
  2265. XThe list of markers may be empty.
  2266. XThere is no limit to the number of markers.
  2267. XExamples of markers are:
  2268. X.nf
  2269. X
  2270. X    queue
  2271. X    /usr/lib
  2272. X    1776
  2273. X    a_long_marker
  2274. X    file[0-9]*.?
  2275. X.fi
  2276. X.SH BINDINGS
  2277. XBindings are the association of names with values.
  2278. XThere is one binding to a line each consisting of a name followed
  2279. Xby an optional sequence of values.
  2280. XNames and values are separated,
  2281. Xone from the other,
  2282. Xby blanks or tabs.
  2283. XHere a newline preceded by a backslash is equivalent to a blank.
  2284. XThe list of bindings may be empty.
  2285. XThere is no limit to the number of bindings.
  2286. XBy convention each binding is indented by a single tab.
  2287. X.SH NAMES
  2288. XNames are arbitrary patterns in the style of
  2289. X.IR glob (3)
  2290. Xdelimited by white space.
  2291. X.SH VALUES
  2292. XValues are
  2293. Xinteger,
  2294. Xreal,
  2295. Xoctal,
  2296. Xhex,
  2297. Xcharacter,
  2298. Xor
  2299. Xstring
  2300. Xconstants.
  2301. XArbitrary text,
  2302. Xnot recognizably one of the aforementioned types,
  2303. Xis classified as
  2304. X.I other
  2305. Xand is a legitimate value.
  2306. X.TP
  2307. Xinteger
  2308. XA sequence of digits optionally preceded by a minus sign.
  2309. XEvery integer constant is taken to be long.
  2310. X.TP
  2311. Xfloating
  2312. XA floating constant consists of an optional minus sign,
  2313. Xan integer part
  2314. Xa decimal point,
  2315. Xa fraction part,
  2316. Xan
  2317. X.B e
  2318. Xor
  2319. X.BR E ,
  2320. Xand an optionally signed integer exponent.
  2321. XThe integer and fraction parts both consist of a sequence of digits.
  2322. XEither the integer part or the fraction part (not both)
  2323. Xmay be missing;
  2324. Xeither the decimal point or the
  2325. X.B e
  2326. Xand the exponent (not both) may be missing.
  2327. XEvery floating constant is taken to be double-precision.
  2328. X.TP
  2329. Xhex
  2330. XA sequence of hexidecimal digits preceded by
  2331. X.B 0x
  2332. Xor
  2333. X.BR 0X .
  2334. XThe hexidecimal digits are 0-9, a-e and A-F.
  2335. XEvery hex constant is taken to be long.
  2336. X.TP
  2337. Xoctal
  2338. XA sequence of octal digits preceded by
  2339. X.B 0o
  2340. Xor
  2341. X.B 0O 
  2342. X(digit zero followed by a letter o).
  2343. XThe octal digits are 0-7.
  2344. XEvery octal constant is taken to be long.
  2345. X.TP
  2346. Xcharacter
  2347. XA character constant is a character enclosed in single quotes.
  2348. XCertain non-graphic characters,
  2349. Xthe single quote ',
  2350. Xthe caret ^ and
  2351. Xthe backslash \\,
  2352. Xmay be represented according to the following table of escape sequences:
  2353. X.ta 1i +\w'carriage return  'u
  2354. X.nf
  2355. X
  2356. X     newline    \\n
  2357. X    horizontal tab    \\t
  2358. X    backspace    \\b
  2359. X    carriage return    \\r
  2360. X    form feed    \\f
  2361. X    escape    \\e
  2362. X    backslash    \\\\
  2363. X    single quote    \\'
  2364. X    caret    \\^
  2365. X    control-@    ^@
  2366. X    control-A    ^A
  2367. X    ...    ...
  2368. X    control-Z    ^Z
  2369. X    control-[    ^[
  2370. X    control-\\    ^\\
  2371. X    control-^    ^^
  2372. X    control-_    ^_
  2373. X    delete    ^?
  2374. X    bit pattern    \\\fIddd\fR
  2375. X
  2376. X.fi
  2377. X.DT
  2378. XThe escape \\\fIddd\fR
  2379. Xconsists of the backslash followed by 1, 2, or 3 octal digits
  2380. Xwhich are taken to specify the value of the desired character.
  2381. XIf the character following a backslash (caret) is not one of those
  2382. Xspecified, the backslash (caret) is ignored.
  2383. X.TP
  2384. Xstring
  2385. XA string is a sequence of characters surrounded by double quotes, as in
  2386. X\fB"..."\fR.
  2387. XIn a string,
  2388. Xthe double quote character \fB"\fR must be preceded by a \\;
  2389. Xin addition,
  2390. Xthe same escapes as described for character constants may be used.
  2391. X.PP
  2392. XExamples of values are:
  2393. X.nf
  2394. X
  2395. X    7
  2396. X    -1.293e3
  2397. X    0x10a5
  2398. X    0o1273
  2399. X    'x'
  2400. X    "a string"
  2401. X    an_other_value
  2402. X.fi
  2403. X.SH COMMENTS
  2404. XComments may appear anywhere within a profile.
  2405. XThey are introduced by the character `#' and are terminated by
  2406. Xthe succeeding newline.
  2407. X.SH EXAMPLES
  2408. XThe empty stanza.
  2409. X.nf
  2410. X
  2411. X{
  2412. X}
  2413. X.fi
  2414. X.PP
  2415. XA stanza in the configuration file of a fictitious network server.
  2416. X.nf
  2417. X.ta \w'queue 'u +\w'cost_per_packet 'u +\w'0o125 0x1af  'u
  2418. X
  2419. Xqueue net*
  2420. X{
  2421. X    priority    7    # integer
  2422. X    expect    "who is it"    # string
  2423. X    send    '?'    # character
  2424. X    flags[0-9]    0o125 0x1af     # octal and hex
  2425. X    cost_per_packet    0.28    # floating
  2426. X    device    /dev/net    # other
  2427. X    homebrew        # a name with no associated value
  2428. X}    
  2429. X.fi
  2430. X.DT
  2431. X.PP
  2432. XA password file entry recast as a stanza.
  2433. X.nf
  2434. X.ta \w'brown 'u +\w'password 'u
  2435. X
  2436. Xbrown
  2437. X{
  2438. X    password    /bObOZtyGclMV
  2439. X    userid    225
  2440. X    groupid    30
  2441. X    home    /home/brown
  2442. X    shell    /bin/csh
  2443. X}
  2444. X.fi
  2445. X.DT
  2446. X.PP
  2447. XA termcap entry recast as a stanza.
  2448. X.nf
  2449. X.ta \w'adm3a 'u +\w'mm 'u
  2450. X
  2451. Xadm3a
  2452. X{
  2453. X    fullname "lsi adm3a"
  2454. X    am
  2455. X    bs
  2456. X    cm    "\\e=%+ %+ "
  2457. X    cl    "1^Z"
  2458. X    co    80
  2459. X    li    24
  2460. X    ho    '^^'
  2461. X    ma    "^K^P"
  2462. X    nd    '^L'
  2463. X    up    '^K'
  2464. X}
  2465. X.fi
  2466. X.SH AUTHOR
  2467. XMichael Gorlick, TRW
  2468. X.SH SEE ALSO
  2469. Xglob(3), profile(3)
  2470. !FaR!OuT!
  2471. if [ ! -d man ]
  2472. then
  2473.     mkdir man
  2474.     echo mkdir man
  2475. fi
  2476. echo x - man/standard.5
  2477. sed -e 's/^X//' > man/standard.5 << '!FaR!OuT!'
  2478. X.\" $Header: standard.5,v 1.1 87/06/23 10:14:41 control Exp $
  2479. X.TH STANDARD 5 TRW
  2480. X.UC
  2481. X.SH NAME
  2482. Xstandard \- standard include file for portability
  2483. X.SH ORIGIN
  2484. XTRW
  2485. X.SH SYNOPSIS
  2486. X#include <local/standard.h>
  2487. X.SH DESCRIPTION
  2488. X.I Standard
  2489. Xis a set of defines, macro definitions and typedefs that provide
  2490. Xportable constructs 
  2491. Xand machine specific information
  2492. Xfor different machine architectures and C compilers.
  2493. XBasically, the include file is divided up into four sections: 
  2494. Xmachine
  2495. Xenvironment
  2496. Xinformation,
  2497. Xstandard type definitions,
  2498. Xuseful constants and useful macros.
  2499. X.PP
  2500. XThe environment of the computer a program is executing on is described by
  2501. Xthe following defines:
  2502. X.TP
  2503. XHAS_UNSIGNED_SHORT
  2504. XIf defined, unsigned shorts are supported.
  2505. X.TP
  2506. XCHAR_IS_SIGNED
  2507. XIf defined, chars are signed.
  2508. X.TP
  2509. XHAS_UNSIGNED_CHAR
  2510. XIf defined, unsigned chars are supported.
  2511. X.TP
  2512. XHAS_UNSIGNED_LONG
  2513. XIf defined, unsigned longs are supported.
  2514. X.TP
  2515. XHAS_VOID
  2516. XIf defined, the void function type is supported.
  2517. X.TP
  2518. XBITS_PER_CHAR
  2519. XDefined as the number of bits in a char.
  2520. X.TP
  2521. XBITS_PER_SHORT
  2522. XDefined as the number of bits in a short.
  2523. X.TP
  2524. XBITS_PER_INT
  2525. XDefined as the number of bits in an int.
  2526. X.TP
  2527. XBITS_PER_LONG
  2528. XDefined as the number of bits in a long.
  2529. X.TP
  2530. XBITS_PER_POINTER
  2531. XDefined as the number of bits in a pointer.
  2532. X.PP
  2533. XThere are a set of machine independent type definitions and macros.
  2534. X.TP
  2535. XTiny
  2536. XA signed character type.
  2537. X.TP
  2538. XTINY(\fIx\fP)
  2539. XAn extraction macro for a signed character.  The value of the macro is an
  2540. Xinteger that will be sign extended if the most significant bit of the 
  2541. Xcharacter is one.
  2542. X.TP
  2543. XUnsignedTiny
  2544. XAn unsigned character type.
  2545. X.TP
  2546. XUNSIGNED_TINY(\fIx\fP)
  2547. XAn extraction macro for an unsigned character.  The value of the macro is an
  2548. Xinteger that will not be signed extended even if the most significant bit
  2549. Xof the character is one.
  2550. X.TP
  2551. XShort
  2552. XSimply a short type.  All compilers have a short type but this is included
  2553. Xfor lexical consistency.
  2554. X.TP
  2555. XUnsignedShort
  2556. XAn unsigned short type.
  2557. X.TP
  2558. XUNSIGNED_SHORT(\fIx\fP)
  2559. XAn extraction macro for an unsigned short.
  2560. XThe value of the macro is an integer that will not be sign extended even if
  2561. Xthe most significant bit of the short is one.
  2562. X.TP
  2563. XInteger
  2564. XThe int type.  Included for lexical consistency.
  2565. X.TP
  2566. XUnsignedInteger
  2567. XThe unsigned integer type.
  2568. X.TP
  2569. XLong
  2570. XThe long type.
  2571. X.TP
  2572. XUnsignedLong
  2573. XAn unsigned long type.
  2574. X.TP
  2575. XUNSIGNED_LONG(\fIx\fP)
  2576. XAn extraction macro for an unsigned long integer.
  2577. XNot all compilers support unsigned longs so we may have to simulate them.
  2578. X.TP
  2579. XTinyBoolean
  2580. XA tiny boolean value.  Boolean types take on only the values TRUE and FALSE.
  2581. X.TP
  2582. XBoolean
  2583. XA regular boolean value.
  2584. X.TP
  2585. XCharacter
  2586. XThe char type.  Included for lexical consistency.
  2587. X.TP
  2588. XTinyBits
  2589. XA type used only for bit set, clear and test operations.
  2590. X.TP
  2591. XBits
  2592. XThe regular size bit type.
  2593. X.TP
  2594. XLongBits
  2595. XThe long size bit type.
  2596. X.TP
  2597. XVoid
  2598. XThe void type.  If the void type is not supported then it is defined as
  2599. Xan int.
  2600. X.TP
  2601. XImport
  2602. XThe storage class used when importing variables from separate files.
  2603. XIt is defined to be the keyword 
  2604. X.I extern.
  2605. X.TP
  2606. XExport
  2607. XThe storage class used when exporting variables from separate files.
  2608. XIn C, you needn't 
  2609. Xdeclare that a variable is available to other files if it is declared
  2610. Xoutside a function so this is defined as a no-op.
  2611. X.TP
  2612. XLocal
  2613. XThe static storage class.
  2614. X.PP
  2615. XA number of useful constants are also defined.
  2616. X.TP
  2617. XTRUE and FALSE
  2618. XThe values 1 and 0 respectively.
  2619. X.TP
  2620. XSUCCEED and FAIL
  2621. XThe values 0 and 1 respectively.  These are normally used as exit statuses.
  2622. X.TP
  2623. XON
  2624. XA long with all the bits set.  
  2625. X.TP
  2626. XOFF
  2627. XA long with no bits set.
  2628. X.TP
  2629. XSTANDARD_IN
  2630. XDefined as 0.
  2631. X.TP
  2632. XSTANDARD_OUT
  2633. XDefined as 1.
  2634. X.TP
  2635. XSTANDARD_ERROR
  2636. XDefined as 2.
  2637. X.TP
  2638. XMAX_TINY
  2639. XThe maximum value a Tiny type can hold.
  2640. X.TP
  2641. XMIN_TINY
  2642. XThe minimum value a Tiny type can hold.
  2643. X.TP
  2644. XMAX_UNSIGNED_TINY
  2645. XThe maximum value an UnsignedTiny type can hold.
  2646. X.TP
  2647. XMIN_UNSIGNED_TINY
  2648. XThe minimum value an UnsignedTiny type can hold.
  2649. X.TP
  2650. XMAX_SHORT
  2651. XThe maximum value a Short type can hold.
  2652. X.TP
  2653. XMIN_SHORT 
  2654. XThe minimum value a Short type can hold.
  2655. X.TP
  2656. XMAX_UNSIGNED_SHORT
  2657. XThe maximum value an UnsignedShort type can hold.
  2658. X.TP
  2659. XMIN_UNSIGNED_SHORT
  2660. XThe minimum value an UnsignedShort type can hold.
  2661. X.TP
  2662. XMAX_INTEGER
  2663. XThe maximum value an Integer type can hold.
  2664. X.TP
  2665. XMIN_INTEGER
  2666. XThe minimum value an Integer type can hold.
  2667. X.TP
  2668. XMAX_UNSIGNED_INTEGER
  2669. XThe maximum value an UnsignedInteger type can hold.
  2670. X.TP
  2671. XMIN_UNSIGNED_INTEGER
  2672. XThe minimum value an UnsignedInteger type can hold.
  2673. X.TP
  2674. XMAX_LONG
  2675. XThe maximum value a Long type can hold.
  2676. X.TP
  2677. XMIN_LONG
  2678. XThe minimum value a Long type can hold.
  2679. X.TP
  2680. XMAX_UNSIGNED_LONG
  2681. XThe maximum value an UnsignedLong type can hold.
  2682. X.TP
  2683. XMIN_UNSIGNED_LONG
  2684. XThe minimum value an UnsignedLong type can hold.
  2685. X.TP
  2686. XBITS_PER_BYTE
  2687. XThe number of bits in a byte.
  2688. X.PP
  2689. XA number of useful macro are also defined.
  2690. X.TP
  2691. XMAX(\fIx\fP, \fIy\fP)
  2692. XReturns the maximum value of 
  2693. X.I x
  2694. Xand 
  2695. X.I y.
  2696. X.TP
  2697. XMIN(\fIx\fP, \fIy\fP)
  2698. XReturns the minimum value of 
  2699. X.I x
  2700. Xand
  2701. X.I y.
  2702. X.TP
  2703. XABS(\fIx\fP)
  2704. XReturns the absolute value of its parameter.  This works for integers and
  2705. Xreals.
  2706. X.TP
  2707. XROUND(\fIx\fP)
  2708. XReturns
  2709. Xits parameter rounded to the nearest integer value.
  2710. X.TP
  2711. XCEILING(\fIx\fP)
  2712. XReturns the ceiling of its parameter.
  2713. X.TP
  2714. XFLOOR(\fIx\fP)
  2715. XReturns the floor of its parameter.
  2716. X.TP
  2717. XEQ(\fIs\fP, \fIt\fP)
  2718. XReturns true if the two strings passed to it as parameters are equal.
  2719. X.TP
  2720. XEQN(\fIs\fP, \fIt\fP, \fIn\fP)
  2721. XReturns true if the two strings passed to it as parameters are equal in
  2722. Xthe first
  2723. X.I n
  2724. Xcharacters (as in
  2725. X.IR strcmp ).
  2726. X.SH FILES
  2727. X.nf
  2728. X.ta \w'/usr/include/local/standenviron.h   'u
  2729. X/usr/include/local/standard.h
  2730. X/usr/include/local/standenviron.h
  2731. X/usr/include/local/standtype.h
  2732. X/usr/include/local/standconst.h
  2733. X/usr/include/local/standmacro.h
  2734. X.fi
  2735. X.SH AUTHOR
  2736. XMichael Gorlick
  2737. !FaR!OuT!
  2738. echo x - shift.c
  2739. sed -e 's/^X//' > shift.c << '!FaR!OuT!'
  2740. Xstatic char *trwsccs = "@(#)shift.c    1.1 (TRW) 1/14/86";
  2741. X#include <ctype.h>
  2742. X
  2743. X/*
  2744. X * Downshifts a string in place.
  2745. X */
  2746. Xchar *string_downshift(s)
  2747. Xchar *s;
  2748. X{
  2749. X
  2750. X    register char *x = s;
  2751. X    for (; *x; x++)
  2752. X        if (isupper(*x))
  2753. X            *x = tolower(*x);
  2754. X    return(s);
  2755. X}
  2756. X
  2757. X/*
  2758. X * Upshifts a string in place.
  2759. X */
  2760. Xchar *string_upshift(s)
  2761. Xchar *s;
  2762. X{
  2763. X
  2764. X    register char *x = s;
  2765. X    for (; *x; x++)
  2766. X        if (islower(*x))
  2767. X            *x = toupper(*x);
  2768. X    return(s);
  2769. X}
  2770. !FaR!OuT!
  2771. exit
  2772.