Annotation of OpenXM/src/ox_toolkit/parse.c, Revision 1.1
1.1 ! ohara 1: /* -*- mode: C; coding: euc-japan -*- */
! 2: /* $OpenXM$ */
! 3:
! 4: /* OX expression, CMO expression パーサ */
! 5:
! 6: #include <stdio.h>
! 7: #include <stdlib.h>
! 8: #include <string.h>
! 9: #include <sys/param.h>
! 10: #include <setjmp.h>
! 11: #include "oxtag.h"
! 12: #include "ox.h"
! 13: #include "parse.h"
! 14:
! 15: /* --- 構文解析部 --- */
! 16: /* (重要)セマンティックスについての注意.
! 17: CMO_LIST, CMO_STRING は、あらかじめ与えられた要素の個数を無視する.
! 18: CMO_MONOMIAL32 は無視しない. (つまりおかしいときは構文エラーになる)
! 19: */
! 20:
! 21: /* parse.c, lex.c では, Lisp 表現された CMO 文字列を読み込み,
! 22: バイト列を出力する. 中間表現として、cmo 構造体を利用する.
! 23: parse() はトークンの列から cmo 構造体を生成し、そのポインタを返す.
! 24: */
! 25:
! 26: /* 重要なことはパーサ(の各サブルーチン)は
! 27: 常にトークンをひとつ先読みしていると言うことである.
! 28: */
! 29:
! 30: /* 現在読み込み中のトークンを表す. */
! 31: static int token = 0;
! 32:
! 33: /* トークンの属性値. yylval は lex() によってセットされる. */
! 34: static union{
! 35: int d;
! 36: char *sym;
! 37: } yylval;
! 38:
! 39: /* pflag_cmo_addrev がセットされていれば、厳密には CMO expression では
! 40: ないもの, 例えば (CMO_STRING, "hello") も CMO に変換される. */
! 41:
! 42: static int pflag_cmo_addrev = 1; /* CMO の省略記法を許すか否かのフラグ */
! 43:
! 44: /* 関数の宣言 */
! 45: static int parse_error(char *s);
! 46: static int parse_lf();
! 47: static int parse_right_parenthesis();
! 48: static int parse_left_parenthesis();
! 49: static int parse_comma();
! 50: static int parse_integer();
! 51: static char *parse_string();
! 52: static cmo *parse_cmo_null();
! 53: static cmo *parse_cmo_int32();
! 54: static cmo *parse_cmo_string();
! 55: static cmo *parse_cmo_mathcap();
! 56: static cmo *parse_cmo_list();
! 57: static cmo *parse_cmo_monomial32();
! 58: static cmo *parse_cmo_zz();
! 59: static cmo *parse_cmo_zero();
! 60: static cmo *parse_cmo_dms_generic();
! 61: static cmo *parse_cmo_ring_by_name();
! 62: static cmo *parse_cmo_distributed_polynomial();
! 63: static cmo *parse_cmo_indeterminate();
! 64: static cmo *parse_cmo_error2();
! 65: static cmo *parse_cmo();
! 66: static int parse_sm();
! 67: static ox *parse_ox();
! 68: static ox *parse_ox_command();
! 69: static ox *parse_ox_data();
! 70:
! 71: static int is_token_cmo(int token)
! 72: {
! 73: return (token >= MIN_T_CMO && token < MAX_T_CMO) || token == TOKEN(CMO_ERROR2);
! 74: }
! 75:
! 76: static int is_token_sm(int token)
! 77: {
! 78: return token == TOKEN(SM);
! 79: }
! 80:
! 81: static int is_token_ox(int token)
! 82: {
! 83: return token >= MIN_T_OX && token < MAX_T_OX;
! 84: }
! 85:
! 86: static jmp_buf env_parse;
! 87:
! 88: /* 構文解析に失敗したことを意味する. */
! 89: static int parse_error(char *s)
! 90: {
! 91: fprintf(stderr, "syntax error: %s\n", s);
! 92: longjmp(env_parse, 1);
! 93: }
! 94:
! 95: /* この部分は書き換え予定. */
! 96: cmo *parse()
! 97: {
! 98: cmo *m;
! 99:
! 100: if (setjmp(env_parse) != 0) {
! 101: return NULL; /* 構文解析に失敗したら NULL を返す. */
! 102: }
! 103:
! 104: do{
! 105: token = lex();
! 106: }while (token == '\n');
! 107:
! 108: if (token == '(') {
! 109: token = lex();
! 110: if (is_token_cmo(token)) {
! 111: m = parse_cmo();
! 112: }else if(is_token_ox(token)) {
! 113: m = parse_ox();
! 114: }else {
! 115: parse_error("invalid symbol.");
! 116: }
! 117: parse_lf();
! 118: return m;
! 119: }
! 120: return NULL;
! 121: }
! 122:
! 123: /* トークンを先読みしない(重要). */
! 124: static int parse_lf()
! 125: {
! 126: if (token != '\n') {
! 127: parse_error("no new line.");
! 128: }
! 129: return 0;
! 130: }
! 131:
! 132:
! 133: static ox *parse_ox()
! 134: {
! 135: ox *m = NULL;
! 136:
! 137: switch(token) {
! 138: case TOKEN(OX_COMMAND):
! 139: token = lex();
! 140: m = parse_ox_command();
! 141: break;
! 142: case TOKEN(OX_DATA):
! 143: token = lex();
! 144: m = parse_ox_data();
! 145: break;
! 146: default:
! 147: parse_error("invalid ox.");
! 148: }
! 149: return m;
! 150: }
! 151:
! 152: static ox *parse_ox_data()
! 153: {
! 154: ox *m;
! 155:
! 156: parse_comma();
! 157: parse_left_parenthesis();
! 158: m = (ox *)new_ox_data(parse_cmo());
! 159: parse_right_parenthesis();
! 160: return m;
! 161: }
! 162:
! 163: static ox *parse_ox_command()
! 164: {
! 165: ox *m;
! 166:
! 167: parse_comma();
! 168: parse_left_parenthesis();
! 169: m = (ox *)new_ox_command(parse_sm());
! 170: parse_right_parenthesis();
! 171: return m;
! 172: }
! 173:
! 174: static int parse_sm()
! 175: {
! 176: int sm_code;
! 177: if (token != TOKEN(SM)) {
! 178: parse_error("no opecode.");
! 179: }
! 180: sm_code = yylval.d;
! 181: token = lex();
! 182: parse_right_parenthesis();
! 183: return sm_code;
! 184: }
! 185:
! 186:
! 187: /* 正しい入力ならば, parse_cmo を呼ぶ時点で, token には
! 188: TOKEN(CMO_xxx), TOKEN(OX_xxx) のいずれかがセットされている. */
! 189: static cmo *parse_cmo()
! 190: {
! 191: cmo *m = NULL;
! 192:
! 193: switch(token) {
! 194: case TOKEN(CMO_NULL):
! 195: token = lex();
! 196: m = parse_cmo_null();
! 197: break;
! 198: case TOKEN(CMO_INT32):
! 199: token = lex();
! 200: m = parse_cmo_int32();
! 201: break;
! 202: case TOKEN(CMO_STRING):
! 203: token = lex();
! 204: m = parse_cmo_string();
! 205: break;
! 206: case TOKEN(CMO_MATHCAP):
! 207: token = lex();
! 208: m = parse_cmo_mathcap();
! 209: break;
! 210: case TOKEN(CMO_LIST):
! 211: token = lex();
! 212: m = parse_cmo_list();
! 213: break;
! 214: case TOKEN(CMO_MONOMIAL32):
! 215: token = lex();
! 216: m = parse_cmo_monomial32();
! 217: break;
! 218: case TOKEN(CMO_ZZ):
! 219: token = lex();
! 220: m = parse_cmo_zz();
! 221: break;
! 222: case TOKEN(CMO_ZERO):
! 223: token = lex();
! 224: m = parse_cmo_zero();
! 225: break;
! 226: case TOKEN(CMO_DMS_GENERIC):
! 227: token = lex();
! 228: m = parse_cmo_dms_generic();
! 229: break;
! 230: case TOKEN(CMO_RING_BY_NAME):
! 231: token = lex();
! 232: m = parse_cmo_ring_by_name();
! 233: break;
! 234: case TOKEN(CMO_DISTRIBUTED_POLYNOMIAL):
! 235: token = lex();
! 236: m = parse_cmo_distributed_polynomial();
! 237: break;
! 238: case TOKEN(CMO_INDETERMINATE):
! 239: token = lex();
! 240: m = parse_cmo_indeterminate();
! 241: break;
! 242: case TOKEN(CMO_ERROR2):
! 243: token = lex();
! 244: m = parse_cmo_error2();
! 245: break;
! 246: default:
! 247: parse_error("invalid cmo.");
! 248: }
! 249: return m;
! 250: }
! 251:
! 252: static int parse_left_parenthesis()
! 253: {
! 254: if (token != '(') {
! 255: parse_error("no left parenthesis.");
! 256: }
! 257: token = lex();
! 258: }
! 259:
! 260: static int parse_right_parenthesis()
! 261: {
! 262: if (token != ')') {
! 263: parse_error("no right parenthesis.");
! 264: }
! 265: token = lex();
! 266: }
! 267:
! 268: static int parse_comma()
! 269: {
! 270: if (token != ',') {
! 271: parse_error("no comma.");
! 272: }
! 273: token = lex();
! 274: }
! 275:
! 276: static int parse_integer()
! 277: {
! 278: int val;
! 279: if (token != T_INTEGER) {
! 280: parse_error("no integer.");
! 281: }
! 282: val = yylval.d;
! 283: token = lex();
! 284: return val;
! 285: }
! 286:
! 287: static char *parse_string()
! 288: {
! 289: char *s;
! 290: if (token != T_STRING) {
! 291: parse_error("no string.");
! 292: }
! 293: s = yylval.sym;
! 294: token = lex();
! 295: return s;
! 296: }
! 297:
! 298: static cmo *parse_cmo_null()
! 299: {
! 300: parse_right_parenthesis();
! 301: return (cmo *)new_cmo_null();
! 302: }
! 303:
! 304: static cmo *parse_cmo_int32()
! 305: {
! 306: int i;
! 307:
! 308: parse_comma();
! 309: i = parse_integer();
! 310: parse_right_parenthesis();
! 311: return (cmo *)new_cmo_int32(i);
! 312: }
! 313:
! 314: static cmo *parse_cmo_string()
! 315: {
! 316: cmo_string *m;
! 317: char *s;
! 318:
! 319: parse_comma();
! 320: if (token == T_INTEGER) {
! 321: parse_integer();
! 322: parse_comma();
! 323: }else if (!pflag_cmo_addrev) {
! 324: parse_error("invalid cmo string.");
! 325: }
! 326: s = parse_string();
! 327: m = new_cmo_string(s);
! 328: parse_right_parenthesis();
! 329: return (cmo *)m;
! 330: }
! 331:
! 332: static cmo *parse_cmo_mathcap()
! 333: {
! 334: cmo *ob;
! 335:
! 336: parse_comma();
! 337: parse_left_parenthesis();
! 338: ob = parse_cmo();
! 339: parse_right_parenthesis();
! 340: return (cmo *)new_cmo_mathcap(ob);
! 341: }
! 342:
! 343: static cmo *parse_cmo_list()
! 344: {
! 345: int length=0;
! 346: int i=0;
! 347: cmo_list *m = new_cmo_list();
! 348: cmo *newcmo;
! 349:
! 350: if (token == ',') {
! 351: parse_comma();
! 352:
! 353: if (token == T_INTEGER) {
! 354: parse_integer();
! 355: parse_comma();
! 356: }else if (!pflag_cmo_addrev) {
! 357: parse_error("invalid cmo_list.");
! 358: }
! 359:
! 360: while(token == '(') {
! 361: parse_left_parenthesis();
! 362: newcmo = parse_cmo();
! 363: append_cmo_list(m, newcmo);
! 364: if (token != ',') {
! 365: break;
! 366: }
! 367: parse_comma();
! 368: }
! 369: }else if (!pflag_cmo_addrev) {
! 370: parse_error("invalid cmo_list.");
! 371: }
! 372: parse_right_parenthesis();
! 373: return (cmo *)m;
! 374: }
! 375:
! 376: static cmo *parse_cmo_monomial32()
! 377: {
! 378: int size;
! 379: int *exps;
! 380: int i;
! 381: cmo_monomial32 *m;
! 382: int tag;
! 383:
! 384: parse_comma();
! 385: size = parse_integer();
! 386: if (size < 0) {
! 387: parse_error("invalid value.");
! 388: }
! 389: m = new_cmo_monomial32_size(size);
! 390:
! 391: for(i=0; i<size; i++) {
! 392: parse_comma();
! 393: m->exps[i] = parse_integer();
! 394: }
! 395: parse_comma();
! 396: parse_left_parenthesis();
! 397: m->coef = parse_cmo();
! 398: tag = m->coef->tag;
! 399:
! 400: /* m->coef は CMO_ZZ 型か CMO_INT32 型でなければならない */
! 401: if (tag != CMO_ZZ && tag != CMO_INT32) {
! 402: parse_error("invalid cmo.");
! 403: }
! 404: parse_right_parenthesis();
! 405: return (cmo *)m;
! 406: }
! 407:
! 408: /* cmo_zz の内部を直接いじる. */
! 409: static cmo *parse_cmo_zz()
! 410: {
! 411: int length;
! 412: int i=0;
! 413: cmo_zz *m= NULL;
! 414:
! 415: parse_comma();
! 416: length = parse_integer();
! 417: if (token == ',') {
! 418: m = new_cmo_zz_size(length);
! 419:
! 420: length = abs(length);
! 421: for(i=0; i<length; i++) {
! 422: parse_comma();
! 423: m->mpz->_mp_d[i] = parse_integer();
! 424: }
! 425: }else if (pflag_cmo_addrev) {
! 426: m = new_cmo_zz_set_si(length);
! 427: }else {
! 428: parse_error("no comma.");
! 429: }
! 430:
! 431: parse_right_parenthesis();
! 432: return (cmo *)m;
! 433: }
! 434:
! 435: static cmo *parse_cmo_zero()
! 436: {
! 437: parse_right_parenthesis();
! 438: return (cmo *)new_cmo_zero();
! 439: }
! 440:
! 441: static cmo *parse_cmo_dms_generic()
! 442: {
! 443: parse_right_parenthesis();
! 444: return (cmo *)new_cmo_dms_generic();
! 445: }
! 446:
! 447: static cmo *parse_cmo_ring_by_name()
! 448: {
! 449: cmo *ob;
! 450:
! 451: parse_comma();
! 452: parse_left_parenthesis();
! 453: ob = parse_cmo();
! 454:
! 455: /* ob は CMO_STRING 型でなければならない */
! 456: if (ob->tag != CMO_STRING) {
! 457: parse_error("invalid cmo.");
! 458: }
! 459: parse_right_parenthesis();
! 460: return (cmo *)new_cmo_ring_by_name(ob);
! 461: }
! 462:
! 463: static cmo *parse_cmo_distributed_polynomial()
! 464: {
! 465: int length=0;
! 466: int i=0;
! 467: cmo_distributed_polynomial *m = new_cmo_distributed_polynomial();
! 468: cmo *ob;
! 469: int tag;
! 470:
! 471: if (token == ',') {
! 472: parse_comma();
! 473:
! 474: if (token == T_INTEGER) {
! 475: parse_integer();
! 476: parse_comma();
! 477: }else if (!pflag_cmo_addrev) {
! 478: parse_error("invalid d-polynomial.");
! 479: }
! 480:
! 481: parse_left_parenthesis();
! 482: m->ringdef = parse_cmo();
! 483: tag = m->ringdef->tag;
! 484: /* m->ringdef は DringDefinition でなければならない */
! 485: if (tag != CMO_RING_BY_NAME && tag != CMO_DMS_GENERIC
! 486: && tag != CMO_DMS_OF_N_VARIABLES) {
! 487: parse_error("invalid cmo.");
! 488: }
! 489:
! 490: parse_comma();
! 491:
! 492: while(token == '(') {
! 493: parse_left_parenthesis();
! 494: ob = parse_cmo();
! 495: if (ob->tag != CMO_MONOMIAL32 && ob->tag != CMO_ZERO) {
! 496: parse_error("invalid cmo.");
! 497: }
! 498: append_cmo_list((cmo_list *)m, ob);
! 499: if (token != ',') {
! 500: break;
! 501: }
! 502: parse_comma();
! 503: }
! 504: }else if (!pflag_cmo_addrev) {
! 505: parse_error("invalid d-polynomial.");
! 506: }
! 507: parse_right_parenthesis();
! 508: return (cmo *)m;
! 509: }
! 510:
! 511: static cmo *parse_cmo_indeterminate()
! 512: {
! 513: cmo *ob;
! 514:
! 515: parse_comma();
! 516: parse_left_parenthesis();
! 517: ob = parse_cmo();
! 518: parse_right_parenthesis();
! 519: return (cmo *)new_cmo_indeterminate(ob);
! 520: }
! 521:
! 522: static cmo *parse_cmo_error2()
! 523: {
! 524: cmo *ob;
! 525:
! 526: parse_comma();
! 527: parse_left_parenthesis();
! 528: ob = parse_cmo();
! 529: parse_right_parenthesis();
! 530: return (cmo *)new_cmo_error2(ob);
! 531: }
! 532:
! 533: /* --- 字句解析部 --- */
! 534:
! 535: /* lexical analyzer で読み飛ばされる文字なら何を初期値にしてもよい */
! 536: static int c = ' ';
! 537:
! 538: /* 一文字読み込む関数 */
! 539: static int (*GETC)() = getchar;
! 540:
! 541: int setgetc(int (*foo)())
! 542: {
! 543: GETC = foo;
! 544: }
! 545:
! 546: int resetgetc()
! 547: {
! 548: GETC = getchar;
! 549: }
! 550:
! 551: #define SIZE_BUFFER 8192
! 552: static char buffer[SIZE_BUFFER];
! 553:
! 554: /* 桁溢れの場合の対策はない */
! 555: static int lex_digit()
! 556: {
! 557: int d = 0;
! 558: do {
! 559: d = 10*d + (c - '0');
! 560: c = GETC();
! 561: } while(isdigit(c));
! 562: return d;
! 563: }
! 564:
! 565: #define MK_KEY_CMO(x) { #x , x , TOKEN(x) , IS_CMO }
! 566: #define MK_KEY_SM(x) { #x , x , TOKEN(SM) , IS_SM }
! 567: #define MK_KEY_OX(x) { #x , x , TOKEN(x) , IS_OX }
! 568:
! 569: static symbol symbol_list[] = {
! 570: MK_KEY_CMO(CMO_NULL),
! 571: MK_KEY_CMO(CMO_INT32),
! 572: MK_KEY_CMO(CMO_DATUM),
! 573: MK_KEY_CMO(CMO_STRING),
! 574: MK_KEY_CMO(CMO_MATHCAP),
! 575: MK_KEY_CMO(CMO_LIST),
! 576: MK_KEY_CMO(CMO_MONOMIAL32),
! 577: MK_KEY_CMO(CMO_ZZ),
! 578: MK_KEY_CMO(CMO_ZERO),
! 579: MK_KEY_CMO(CMO_DMS_GENERIC),
! 580: MK_KEY_CMO(CMO_RING_BY_NAME),
! 581: MK_KEY_CMO(CMO_INDETERMINATE),
! 582: MK_KEY_CMO(CMO_DISTRIBUTED_POLYNOMIAL),
! 583: MK_KEY_CMO(CMO_ERROR2),
! 584: MK_KEY_SM(SM_popCMO),
! 585: MK_KEY_SM(SM_popString),
! 586: MK_KEY_SM(SM_mathcap),
! 587: MK_KEY_SM(SM_pops),
! 588: MK_KEY_SM(SM_executeStringByLocalParser),
! 589: MK_KEY_SM(SM_executeFunction),
! 590: MK_KEY_SM(SM_setMathCap),
! 591: MK_KEY_SM(SM_shutdown),
! 592: MK_KEY_SM(SM_control_kill),
! 593: MK_KEY_SM(SM_control_reset_connection),
! 594: MK_KEY_OX(OX_COMMAND),
! 595: MK_KEY_OX(OX_DATA),
! 596: {NULL, 0, 0, 0} /* a gate keeper */
! 597: };
! 598:
! 599: symbol* lookup_by_symbol(char *key)
! 600: {
! 601: symbol *symp;
! 602: for(symp = symbol_list; symp->key != NULL; symp++) {
! 603: if (strcmp(key, symp->key)==0) {
! 604: return symp;
! 605: }
! 606: }
! 607: return NULL;
! 608: }
! 609:
! 610: symbol* lookup_by_token(int tok)
! 611: {
! 612: symbol *symp;
! 613: for(symp = symbol_list; symp->key != NULL; symp++) {
! 614: if (tok == symp->token) {
! 615: return symp;
! 616: }
! 617: }
! 618: return NULL;
! 619: }
! 620:
! 621: symbol* lookup_by_tag(int tag)
! 622: {
! 623: symbol *symp;
! 624: for(symp = symbol_list; symp->key != NULL; symp++) {
! 625: if (tag == symp->tag) {
! 626: return symp;
! 627: }
! 628: }
! 629: return NULL;
! 630: }
! 631:
! 632: symbol* lookup(int i)
! 633: {
! 634: return &symbol_list[i];
! 635: }
! 636:
! 637: /* バッファあふれした場合の対策をちゃんと考えるべき */
! 638: static char *lex_quoted_string()
! 639: {
! 640: int i;
! 641: char c0 = ' ';
! 642: char *s = NULL;
! 643: for (i=0; i<SIZE_BUFFER; i++) {
! 644: c = GETC();
! 645: if(c == '"') {
! 646: s = malloc(i+1);
! 647: buffer[i]='\0';
! 648: strcpy(s, buffer);
! 649:
! 650: c = GETC();
! 651: return s;
! 652: }else if (c == '\\') {
! 653: c0 = c;
! 654: c = GETC();
! 655: if (c != '"') {
! 656: buffer[i++] = c0;
! 657: }
! 658: }
! 659: buffer[i]=c;
! 660: }
! 661: fprintf(stderr, "buffer overflow!\n");
! 662: exit(1);
! 663: /* return NULL; */
! 664: }
! 665:
! 666: static int token_of_symbol(char *key)
! 667: {
! 668: symbol *symp = lookup_by_symbol(key);
! 669: if (symp != NULL) {
! 670: yylval.d = symp->tag;
! 671: return symp->token;
! 672: }
! 673: #if DEBUG
! 674: fprintf(stderr, "lex error:: \"%s\" is unknown symbol.\n", key);
! 675: #endif
! 676: return 0;
! 677: }
! 678:
! 679: static int lex_symbol()
! 680: {
! 681: int i;
! 682: for (i=0; i<SIZE_BUFFER; i++) {
! 683: if (!isalnum(c) && c != '_') {
! 684: buffer[i]='\0';
! 685: return token_of_symbol(buffer);
! 686: }
! 687: buffer[i]=c;
! 688: c = GETC();
! 689: }
! 690: fprintf(stderr, "buffer overflow!\n");
! 691: return 0;
! 692: }
! 693:
! 694: /* return する前に一文字先読みしておく. */
! 695: int lex()
! 696: {
! 697: int c_dash = 0;
! 698:
! 699: /* 空白をスキップする. */
! 700: while (isspace(c) && c != '\n') {
! 701: c = GETC();
! 702: }
! 703:
! 704: switch(c) {
! 705: case '(':
! 706: case ')':
! 707: case ',':
! 708: case '\n':
! 709: c_dash = c;
! 710: c = ' ';
! 711: return c_dash;
! 712: case EOF:
! 713: c = GETC();
! 714: return c_dash;
! 715: case '"': /* a quoted string! */
! 716: yylval.sym = lex_quoted_string();
! 717: return T_STRING;
! 718: default:
! 719: }
! 720:
! 721: if (isalpha(c)) { /* 識別子 */
! 722: return lex_symbol();
! 723: }
! 724:
! 725: /* 32bit 整数値 */
! 726: if (isdigit(c)){
! 727: yylval.d = lex_digit();
! 728: return T_INTEGER;
! 729: }
! 730: if (c == '-') {
! 731: c = GETC();
! 732: while (isspace(c) && c != '\n') {
! 733: c = GETC();
! 734: }
! 735: if (isdigit(c)){
! 736: yylval.d = - lex_digit();
! 737: return T_INTEGER;
! 738: }
! 739: return 0;
! 740: }
! 741:
! 742: c = GETC();
! 743: return 0;
! 744: }
! 745:
! 746: /* 一文字読み込む関数 */
! 747: static char *mygetc_line;
! 748: static int mygetc_counter;
! 749: static int mygetc_counter_max;
! 750: static int mygetc_nonlf_flag;
! 751:
! 752: int mygetc()
! 753: {
! 754: int c = '\0';
! 755:
! 756: if (mygetc_nonlf_flag && mygetc_counter <= mygetc_counter_max) {
! 757: c = mygetc_line[mygetc_counter++];
! 758: if (c == '\0') {
! 759: c = '\n';
! 760: mygetc_nonlf_flag = 0;
! 761: }
! 762: }
! 763: return c;
! 764: }
! 765:
! 766: int setmode_mygetc(char *s, int len)
! 767: {
! 768: mygetc_nonlf_flag=1;
! 769: mygetc_counter=0;
! 770: mygetc_counter_max=len;
! 771: mygetc_line=s;
! 772: }
! 773:
! 774: int setflag_parse(int flag)
! 775: {
! 776: pflag_cmo_addrev = flag;
! 777: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>