2 *------------------------------------------------------------------
3 * lex.c - API generator lexical analyzer
5 * Copyright (c) 1996-2009 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
29 #include "tools/vppapigen/gram.h"
30 #include <vppinfra/clib.h>
31 #include <vppinfra/fifo.h>
32 #include <vppinfra/format.h>
34 FILE *ifp, *ofp, *pythonfp, *jsonfp;
35 char *vlib_app_name = "vpp";
39 char *current_filename;
40 int current_filename_allocated;
41 unsigned long input_crc;
42 unsigned long message_crc;
44 char *push_input_fifo;
45 char saved_ungetc_char;
46 char have_ungetc_char;
49 * lexer variable definitions
52 static const char *version = "0.1";
53 static int the_lexer_linenumber = 1;
54 static enum lex_state the_lexer_state = START_STATE;
59 static void usage (char *);
60 static int name_check (const char *, YYSTYPE *);
61 static int name_compare (const char *, const char *);
63 extern YYSTYPE yylval;
65 unsigned int crc32c_table[256] = {
66 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
67 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
68 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
69 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
70 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
71 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
72 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
73 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
74 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
75 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
76 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
77 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
78 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
79 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
80 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
81 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
82 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
83 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
84 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
85 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
86 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
87 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
88 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
89 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
90 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
91 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
92 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
93 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
94 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
95 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
96 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
97 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
98 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
99 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
100 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
101 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
102 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
103 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
104 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
105 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
106 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
107 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
108 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
109 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
110 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
111 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
112 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
113 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
114 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
115 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
116 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
117 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
118 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
119 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
120 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
121 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
122 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
123 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
124 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
125 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
126 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
127 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
128 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
129 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
132 static inline unsigned long CRC8 (unsigned long crc,
135 return ((crc >> 8) ^ crc32c_table[(crc ^ d) & 0xFF]);
137 static inline unsigned long CRC16 (unsigned long crc,
140 crc = CRC8 (crc, d & 0xff);
142 crc = CRC8 (crc, d & 0xff);
148 crc_eliding_c_comments (const char *buf, unsigned long crc)
153 cSBACKSLASH, /* "...\ */
155 cCBACKSLASH, /* '...\ */
157 cSLASH_SLASH, /* //... */
158 cSLASH_STAR, /* / *... */
163 unsigned char c = *p++;
170 case cSTRING: case cSBACKSLASH:
171 case cCHAR: case cCBACKSLASH:
172 case cSLASH: case cSLASH_SLASH: case cSLASH_STAR: case cSTAR:
173 fprintf (stderr, "Inopportune EOF: %s\n", buf);
179 case cOTHER: ss = cSTRING; break; /* start string */
180 case cSTRING: ss = cOTHER; break; /* end string */
181 case cSBACKSLASH: ss = cSTRING; break;
183 case cCBACKSLASH: ss = cCHAR; break;
184 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
185 case cSLASH_SLASH: continue; /* in comment */
186 case cSLASH_STAR: continue; /* in comment */
187 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
193 case cSTRING: ss = cSBACKSLASH; break;
194 case cSBACKSLASH: ss = cSTRING; break;
195 case cCHAR: ss = cCBACKSLASH; break;
196 case cCBACKSLASH: ss = cCHAR; break;
197 case cSLASH: crc = CRC8 (crc, '/'); ; ss = cOTHER; break;
198 case cSLASH_SLASH: continue; /* in comment */
199 case cSLASH_STAR: continue; /* in comment */
200 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
205 case cOTHER: ss = cSLASH; continue; /* potential comment */
207 case cSBACKSLASH: ss = cSTRING; break;
209 case cCBACKSLASH: ss = cCHAR; break;
210 case cSLASH: ss = cSLASH_SLASH; continue; /* start comment */
211 case cSLASH_SLASH: continue; /* in comment */
212 case cSLASH_STAR: continue; /* in comment */
213 case cSTAR: ss = cOTHER; continue; /* end of comment */
220 case cSBACKSLASH: ss = cSTRING; break;
222 case cCBACKSLASH: ss = cCHAR; break;
223 case cSLASH: ss = cSLASH_STAR; continue; /* start comment */
224 case cSLASH_SLASH: continue; /* in comment */
225 case cSLASH_STAR: ss = cSTAR; continue; /* potential end */
226 case cSTAR: continue; /* still potential end of comment */
229 case '\n': case '\r': case ' ': case '\t': case '\014':
231 case cOTHER: continue; /* ignore all whitespace */
233 case cSBACKSLASH: ss = cSTRING; break;
235 case cCBACKSLASH: ss = cCHAR; break;
236 case cSLASH: c = '/'; ss = cOTHER; break;
238 if (c == '\n' || c == '\r') ss = cOTHER; /* end comment */
240 case cSLASH_STAR: continue; /* in comment */
241 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
247 case cSBACKSLASH: ss = cSTRING; break;
249 case cCBACKSLASH: ss = cCHAR; break;
250 case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
251 case cSLASH_SLASH: continue; /* in comment */
252 case cSLASH_STAR: continue; /* in comment */
253 case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
263 int main (int argc, char **argv)
271 while (curarg < argc) {
272 if (!strncmp (argv [curarg], "--verbose", 3)) {
273 fprintf (stderr, "%s version %s\n", argv [0], version);
278 if (!strncmp (argv [curarg], "--yydebug", 3)) {
284 if (!strncmp (argv [curarg], "--dump", 3)) {
290 if (!strncmp (argv[curarg], "--show-name", 3)) {
293 show_name = argv[curarg];
297 fprintf(stderr, "Missing filename after --show-name \n");
302 if (!strncmp (argv [curarg], "--input", 3)) {
305 input_filename = argv[curarg];
306 if (!strcmp (argv [curarg], "-"))
309 ifp = fopen (argv [curarg], "r");
311 fprintf (stderr, "Couldn't open input file %s\n",
317 fprintf(stderr, "Missing filename after --input\n");
322 if (!strncmp (argv [curarg], "--output", 3)) {
325 ofp = fopen (argv[curarg], "w");
327 fprintf (stderr, "Couldn't open output file %s\n",
331 ofile = argv[curarg];
334 fprintf(stderr, "Missing filename after --output\n");
339 if (!strncmp (argv [curarg], "--python", 8)) {
342 if (!strcmp(argv[curarg], "-")) {
345 pythonfp = fopen(argv[curarg], "w");
346 pythonfile = argv[curarg];
348 if (pythonfp == NULL) {
349 fprintf (stderr, "Couldn't open python output file %s\n",
355 fprintf(stderr, "Missing filename after --python\n");
360 if (!strncmp (argv [curarg], "--json", 6)) {
363 if (!strcmp(argv[curarg], "-")) {
366 jsonfp = fopen(argv[curarg], "w");
367 jsonfile = argv[curarg];
369 if (jsonfp == NULL) {
370 fprintf (stderr, "Couldn't open JSON output file %s\n",
376 fprintf(stderr, "Missing filename after --json\n");
381 if (!strncmp (argv [curarg], "--app", 4)) {
384 vlib_app_name = argv[curarg];
387 fprintf(stderr, "Missing app name after --app\n");
399 if (pythonfp == NULL) {
402 if (jsonfp == NULL) {
406 fprintf(stderr, "No input file specified...\n");
410 input_filename = show_name;
413 starttime = time (0);
415 if (yyparse() == 0) {
419 printf ("Output written to %s\n", ofile);
423 printf ("Python bindings written to %s\n", pythonfile);
427 printf ("JSON bindings written to %s\n", jsonfile);
436 printf ("Removing %s\n", ofile);
440 printf ("Removing %s\n", pythonfile);
444 printf ("Removing %s\n", jsonfile);
455 static void usage (char *progname)
458 "usage: %s --input <filename> [--output <filename>] "
459 "[--json <filename>] [--python <filename>]\n%s",
461 " [--yydebug] [--dump-tree]\n");
468 void yyerror (char *s)
470 fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
473 static char namebuf [MAXNAME];
476 getc_char (FILE *ifp)
480 if (have_ungetc_char) {
481 have_ungetc_char = 0;
482 return saved_ungetc_char;
485 if (clib_fifo_elts (push_input_fifo)) {
486 clib_fifo_sub1(push_input_fifo, rv);
489 return ((char)(getc(ifp) & 0x7f));
494 return clib_fifo_elts (fifo);
498 ungetc_char (char c, FILE *ifp)
500 saved_ungetc_char = c;
501 have_ungetc_char = 1;
504 void autoreply (void *np_arg)
507 node_t *np = (node_t *)np_arg;
510 vec_reset_length (s);
512 s = format (0, " define %s_reply\n", (char *)(np->data[0]));
513 s = format (s, "{\n");
514 s = format (s, " u32 context;\n");
515 s = format (s, " i32 retval;\n");
516 s = format (s, "};\n");
518 for (i = 0; i < vec_len (s); i++)
519 clib_fifo_add1 (push_input_fifo, s[i]);
523 * yylex (well, yylex_1: The real yylex below does crc-hackery)
525 static int yylex_1 (void)
529 enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
530 LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
533 } lp_substate = LP_INITIAL_WHITESPACE;
536 switch (the_lexer_state) {
538 * START state -- looking for something interesting
547 the_lexer_linenumber++;
551 the_lexer_state = LINE_PRAGMA_STATE;
552 lp_substate = LP_INITIAL_WHITESPACE;
586 the_lexer_state = STRING_STATE;
591 the_lexer_state = HELPER_STATE;
600 the_lexer_state = CPP_COMMENT_STATE;
602 } else if (c == '*') {
603 the_lexer_state = C_COMMENT_STATE;
606 fprintf (stderr, "unknown token /%c at line %d\n",
607 c, the_lexer_linenumber);
616 /* Note fallthrough... */
619 if (isalpha (c) || c == '_') {
622 the_lexer_state = NAME_STATE;
624 } else if (isdigit(c)) {
627 the_lexer_state = NUMBER_STATE;
631 fprintf (stderr, "unknown token %c at line %d\n",
632 c, the_lexer_linenumber);
637 * NAME state -- eat the rest of a name
644 if (!isalnum (c) && c != '_') {
645 ungetc_char (c, ifp);
646 namebuf [nameidx] = 0;
647 the_lexer_state = START_STATE;
648 return (name_check (namebuf, &yylval));
650 if (nameidx >= (MAXNAME-1)) {
651 fprintf(stderr, "lex input buffer overflow...\n");
654 namebuf [nameidx++] = c;
658 * NUMBER state -- eat the rest of a number
666 ungetc_char (c, ifp);
667 namebuf [nameidx] = 0;
668 the_lexer_state = START_STATE;
669 yylval = (void *) atol(namebuf);
672 if (nameidx >= (MAXNAME-1)) {
673 fprintf(stderr, "lex input buffer overflow...\n");
676 namebuf [nameidx++] = c;
680 * C_COMMENT state -- eat a peach
682 case C_COMMENT_STATE:
691 the_lexer_state = START_STATE;
696 the_lexer_linenumber++;
700 * CPP_COMMENT state -- eat a plum
703 case CPP_COMMENT_STATE:
708 the_lexer_linenumber++;
709 the_lexer_state = START_STATE;
723 namebuf[nameidx++] = c;
727 namebuf[nameidx] = 0;
728 yylval = (YYSTYPE) sxerox (namebuf);
729 the_lexer_state = START_STATE;
734 the_lexer_linenumber++;
736 if (nameidx >= (MAXNAME-1)) {
737 fprintf(stderr, "lex input buffer overflow...\n");
740 namebuf[nameidx++] = c;
754 namebuf[nameidx] = c;
758 namebuf[nameidx] = 0;
759 yylval = (YYSTYPE) sxerox (namebuf);
760 the_lexer_state = START_STATE;
761 return (HELPER_STRING);
765 the_lexer_linenumber++;
768 * CPP makes it approximately impossible to
769 * type "#define FOO 123", so we provide a
770 * lexical trick to achieve that result
776 if (nameidx >= (MAXNAME-1)) {
777 fprintf(stderr, "lex input buffer overflow...\n");
780 namebuf[nameidx++] = c;
785 case LINE_PRAGMA_STATE:
786 /* We're only interested in lines of the form # 259 "foo.c" 17 */
788 switch (lp_substate) {
790 case LP_INITIAL_WHITESPACE: /* no number seen yet */
794 if (c >= '0' && c <= '9') {
795 namebuf[nameidx++] = c;
796 lp_substate = LP_LINE_NUMBER;
797 } else if (c == '\n') {
799 } else if (c != ' ' && c != '\t') {
802 lp_substate = LP_OTHER;
806 case LP_LINE_NUMBER: /* eating linenumber */
810 if (c >= '0' && c <= '9') {
811 namebuf[nameidx++] = c;
812 } else if (c == ' ' || c == '\t') {
813 namebuf[nameidx++] = 0;
814 the_lexer_linenumber = atol(namebuf);
815 lp_substate = LP_PRE_FILENAME_WHITESPACE;
816 } else if (c == '\n') {
819 lp_substate = LP_OTHER;
823 case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
829 lp_substate = LP_FILENAME;
831 } else if (c == ' ' || c == '\t') {
833 } else if (c == '\n') {
836 lp_substate = LP_OTHER;
840 case LP_FILENAME: /* eating filename */
846 lp_substate = LP_POST_FILENAME;
847 namebuf[nameidx] = 0;
848 } else if (c == '\n') {
849 goto lp_end_of_line; /* syntax error... */
851 namebuf[nameidx++] = c;
855 case LP_POST_FILENAME: /* ignoring rest of line */
862 if (lp_substate == LP_POST_FILENAME) {
863 if (current_filename_allocated) {
864 current_filename_allocated = 0;
865 free(current_filename);
868 if (!strcmp(namebuf, "<stdin>")) {
869 current_filename = input_filename;
871 current_filename = sxerox(namebuf);
872 current_filename_allocated = 1;
876 the_lexer_state = START_STATE;
883 fprintf (stderr, "LEXER BUG!\n");
890 * Parse a token and side-effect input_crc
891 * in a whitespace- and comment-insensitive fashion.
896 * Accumulate a crc32-based signature while processing the
897 * input file. The goal is to come up with a magic number
898 * which changes precisely when the original input file changes
899 * but which ignores whitespace changes.
901 unsigned long crc = input_crc;
902 int node_type = yylex_1 ();
903 unsigned long crc2 = message_crc;
904 int use_helper_string = 0;
913 use_helper_string = 1;
916 /* Other node types have no "substate" */
917 /* This code is written in this curious fashion because we
918 * want the generated CRC to be independent of the particular
919 * values a particular version of lex/bison assigned to various states.
922 case RPAR: code = 258; break;
923 case LPAR: code = 259; break;
924 case SEMI: code = 260; break;
925 case LBRACK: code = 261; break;
926 case RBRACK: code = 262; break;
927 case BARF: code = 265; break;
928 case TPACKED: code = 266; break;
929 case DEFINE: code = 267; break;
930 case LCURLY: code = 268; break;
931 case RCURLY: code = 269; break;
932 case UNION: code = 271; break;
933 case COMMA: code = 273; break;
934 case NOVERSION: code = 274; break;
935 case MANUAL_PRINT: code = 275; break;
936 case MANUAL_ENDIAN: code = 276; break;
937 case TYPEONLY: code = 278; break;
938 case DONT_TRACE: code = 279; break;
939 case AUTOREPLY: code = 280; break;
941 case EOF: code = ~0; break; /* hysterical compatibility */
944 fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
949 if (use_helper_string)
951 /* We know these types accumulated token text into namebuf */
952 /* HELPER_STRING may still contain C comments. Argh. */
953 crc = crc_eliding_c_comments (namebuf, crc);
954 crc2 = crc_eliding_c_comments (namebuf, crc2);
957 crc = CRC16 (crc, code);
958 crc2 = CRC16 (crc2, code);
967 * name_check -- see if the name we just ate
968 * matches a known keyword. If so, set yylval
969 * to a new instance of <subclass of node>, and return PARSER_MACRO
971 * Otherwise, set yylval to sxerox (s) and return NAME
974 static struct keytab {
976 enum node_subclass subclass_id;
978 /* Keep the table sorted, binary search used below! */
980 {"autoreply", NODE_AUTOREPLY},
981 {"define", NODE_DEFINE},
982 {"dont_trace", NODE_DONT_TRACE},
988 {"manual_endian", NODE_MANUAL_ENDIAN},
989 {"manual_print", NODE_MANUAL_PRINT},
990 {"noversion", NODE_NOVERSION},
991 {"packed", NODE_PACKED},
992 {"typeonly", NODE_TYPEONLY},
997 {"union", NODE_UNION},
998 {"uword", NODE_UWORD},
1001 static int name_check (const char *s, YYSTYPE *token_value)
1003 enum node_subclass subclass_id;
1007 for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1;
1009 mid = (top + bot) / 2;
1010 result = name_compare (s, keytab[mid].name);
1013 else if (result > 0)
1016 subclass_id = keytab[mid].subclass_id;
1018 switch (subclass_id) {
1029 *token_value = make_node(subclass_id);
1033 *token_value = make_node(subclass_id);
1038 *token_value = make_node(subclass_id);
1041 case NODE_MANUAL_PRINT:
1042 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
1043 return (MANUAL_PRINT);
1045 case NODE_MANUAL_ENDIAN:
1046 *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
1047 return (MANUAL_ENDIAN);
1050 *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
1053 case NODE_DONT_TRACE:
1054 *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
1057 case NODE_AUTOREPLY:
1058 *token_value = (YYSTYPE) NODE_FLAG_AUTOREPLY;
1061 case NODE_NOVERSION:
1068 fprintf (stderr, "fatal: keytab botch!\n");
1073 *token_value = (YYSTYPE) sxerox (s);
1081 char *sxerox (const char *s)
1083 int len = strlen (s);
1086 rv = (char *) malloc (len+1);
1088 fprintf(stderr, "Out of memory...");
1100 int name_compare (const char *s1, const char *s2)
1104 while (*s1 && *s2) {