1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright (c) 1995 by Sun Microsystems, Inc. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <limits.h> 31 #include <string.h> 32 #include <libintl.h> 33 #include <locale.h> 34 #include "genmsg.h" 35 #include "y.tab.h" 36 37 extern int is_cat_found; /* from main.c */ 38 extern void add_comment(Mode, char *);/* from util.c */ 39 40 int lineno = 1; 41 42 /* 43 * msg_line stores the line number where a msgid is to be replaced. 44 */ 45 int msg_line = 0; 46 47 int end_of_cat = TRUE; 48 49 /* 50 * In preprocessor mode, genmsg has to parse both the original 51 * soruce code and the code which a preprocessor generates. 52 * While genmsg is parsing the original source code, 'pound_is_mine' 53 * is set to TRUE. 54 */ 55 int pound_is_mine = FALSE; 56 57 void warning(char *); 58 59 #define NOLINEMSG -2 60 61 void set_linemsgid(int, int); 62 int get_linemsgid(int); 63 64 /* 65 * cat_field indicates which token is currently parsed by lex. 66 */ 67 #define CatdField 0 68 #define SetidField 1 69 #define MsgidField 2 70 #define StrField 3 71 72 static int cat_field; 73 74 /* 75 * This will be turned on when '-' is found in the catgets message 76 * number field. 77 */ 78 static int save_minus = FALSE; 79 80 static char *skip_quoted(int skip_ch); 81 static char *skip_comment(void); 82 static void parse_cppline(char *); 83 %} 84 %s CAT 85 %% 86 87 [0-9a-zA-Z\_\.]catgets { 88 if (IsActiveMode(ReplaceMode)) { 89 fprintf(newfp, "%s", yytext); 90 } 91 } 92 93 catgets[0-9a-zA-Z\_\.] { 94 if (IsActiveMode(ReplaceMode)) { 95 fprintf(newfp, "%s", yytext); 96 } 97 } 98 99 catgets { 100 if (end_of_cat) { /* If the previous catgets 101 * state is on, turn it off 102 * first. 103 */ 104 BEGIN 0; 105 } 106 if (IsActiveMode(ReplaceMode)) { 107 fprintf(newfp, "%s", yytext); 108 } 109 if (IsActiveMode(ReplaceMode) && 110 IsActiveMode(PreProcessMode)) { 111 ; /* Okay, do nothing in this mode. */ 112 } else { 113 BEGIN CAT; 114 end_of_cat = FALSE; 115 cat_field = CatdField; 116 return CATGETS; 117 } 118 } 119 120 <CAT>\, { /* punctuation */ 121 cat_field++; 122 if (IsActiveMode(ReplaceMode)) { 123 fprintf(newfp, "%c", yytext[0]); 124 } 125 if (end_of_cat) { 126 BEGIN 0; 127 } else { 128 return yytext[0]; 129 } 130 } 131 132 <CAT>[+*/();>] { /* punctuation */ 133 if (IsActiveMode(ReplaceMode)) { 134 fprintf(newfp, "%c", yytext[0]); 135 } 136 if (end_of_cat) { 137 BEGIN 0; 138 } else { 139 return yytext[0]; 140 } 141 } 142 143 <CAT>const { 144 if (IsActiveMode(ReplaceMode)) { 145 fprintf(newfp, "%s", yytext); 146 } 147 if (end_of_cat) { 148 BEGIN 0; 149 } else { 150 return CONST; 151 } 152 } 153 154 <CAT>nl_catd { 155 if (IsActiveMode(ReplaceMode)) { 156 fprintf(newfp, "%s", yytext); 157 } 158 if (end_of_cat) { 159 BEGIN 0; 160 } else { 161 return CATD; 162 } 163 } 164 165 <CAT>char { 166 if (IsActiveMode(ReplaceMode)) { 167 fprintf(newfp, "%s", yytext); 168 } 169 if (end_of_cat) { 170 BEGIN 0; 171 } else { 172 return CHAR; 173 } 174 } 175 176 <CAT>int { 177 if (IsActiveMode(ReplaceMode)) { 178 fprintf(newfp, "%s", yytext); 179 } 180 if (end_of_cat) { 181 BEGIN 0; 182 } else { 183 return INT; 184 } 185 } 186 187 <CAT>\+\+ { 188 if (IsActiveMode(ReplaceMode)) { 189 fprintf(newfp, "%s", yytext); 190 } 191 if (end_of_cat) { 192 BEGIN 0; 193 } else { 194 return INC; 195 } 196 } 197 198 <CAT>\-\- { 199 if (IsActiveMode(ReplaceMode)) { 200 fprintf(newfp, "%s", yytext); 201 } 202 if (end_of_cat) { 203 BEGIN 0; 204 } else { 205 return INC; 206 } 207 } 208 209 <CAT>\" { /* extract quoted string */ 210 yylval.str = skip_quoted('"'); 211 if (IsActiveMode(ReplaceMode)) { 212 fprintf(newfp, "\"%s\"", yylval.str); 213 } 214 if (end_of_cat) { /* just in case */ 215 BEGIN 0; 216 free(yylval.str); 217 } else { 218 return QSTR; 219 } 220 } 221 222 <CAT>- { /* punctuation */ 223 if (IsActiveMode(ReplaceMode)) { 224 if (cat_field == MsgidField && 225 get_linemsgid(lineno) != NOLINEMSG) { 226 save_minus = TRUE; /* be replaced. */ 227 } else { 228 fprintf(newfp, "%c", yytext[0]); 229 } 230 } 231 if (end_of_cat) { /* just in case */ 232 BEGIN 0; 233 } else { 234 return yytext[0]; 235 } 236 } 237 238 <CAT>[0-9]+ { /* numbers */ 239 switch (cat_field) { 240 case SetidField: 241 yylval.id = atoi(yytext); 242 if (IsActiveMode(ReplaceMode)) { 243 fprintf(newfp, "%s", yytext); 244 } 245 if (end_of_cat) { 246 BEGIN 0; 247 } else { 248 return SETID; 249 } 250 case MsgidField: 251 yylval.id = atoi(yytext); 252 if (IsActiveMode(ReplaceMode)) { 253 int id = get_linemsgid(lineno); 254 if (id == NOLINEMSG) { 255 fprintf(newfp, "%s", yytext); 256 } else if (id == NOMSGID && 257 IsActiveMode(ReverseMode)) { 258 fprintf(newfp, "%d", NOMSGID); 259 } else if (save_minus == TRUE && 260 yylval.id == 1) { 261 fprintf(newfp, "%d",id); 262 } else { /* just in case */ 263 fprintf(newfp, "%s", yytext); 264 } 265 save_minus = FALSE; 266 } else { 267 msg_line = lineno; 268 } 269 if (end_of_cat) { 270 BEGIN 0; 271 } else { 272 return MSGID; 273 } 274 default: 275 yylval.id = atoi(yytext); 276 if (IsActiveMode(ReplaceMode)) { 277 fprintf(newfp, "%s", yytext); 278 } 279 if (end_of_cat) { 280 BEGIN 0; 281 } else { 282 return DIGIT; 283 } 284 } 285 } 286 287 <CAT>[a-zA-Z0-9_\&][a-zA-Z0-9_\>\&\.]* { 288 if (IsActiveMode(ReplaceMode)) { 289 fprintf(newfp, "%s", yytext); 290 } 291 if (end_of_cat) { 292 BEGIN 0; 293 } else { 294 return STR; 295 } 296 } 297 298 <CAT>\n { 299 lineno++; 300 if (IsActiveMode(ReplaceMode)) { 301 fprintf(newfp, "\n"); 302 } 303 if (end_of_cat) { 304 BEGIN 0; 305 } 306 } 307 308 <CAT>. { /* not interested */ 309 if (IsActiveMode(ReplaceMode)) { 310 fprintf(newfp, "%c", yytext[0]); 311 } 312 if (end_of_cat) { 313 BEGIN 0; 314 } 315 } 316 317 -((([ \t]+)1)|1) { /* -1 */ 318 if (end_of_cat == FALSE) { 319 REJECT; 320 } else if (IsActiveMode(ReplaceMode)) { 321 if (IsActiveMode(PreProcessMode)) { 322 int id = get_linemsgid(lineno); 323 if (id == NOLINEMSG) { 324 fprintf(newfp, "%s", yytext); 325 } else { /* could be -1. */ 326 fprintf(newfp, "%d", id); 327 } 328 } else { 329 fprintf(newfp, "%s", yytext); 330 } 331 } 332 } 333 334 [0-9]+ { 335 if (IsActiveMode(ReplaceMode)) { 336 if (IsActiveMode(PreProcessMode) && 337 IsActiveMode(ReverseMode)) { 338 int id = get_linemsgid(lineno); 339 if (id == NOLINEMSG) { 340 fprintf(newfp, "%s", yytext); 341 } else if (id == NOMSGID) { 342 fprintf(newfp, "%d", id); 343 } 344 } else { 345 fprintf(newfp, "%s", yytext); 346 } 347 } 348 } 349 350 ^#[ \t]*[0-9]+.*\n { /* pound for c-preprocessor */ 351 if (IsActiveMode(PreProcessMode)) { 352 if (IsActiveMode(ReplaceMode)) { 353 fprintf(newfp, "%s", yytext); 354 } else { 355 parse_cppline(yytext); 356 } 357 } else if (IsActiveMode(ReplaceMode)) { 358 fprintf(newfp, "%s", yytext); 359 } 360 lineno++; 361 } 362 363 "/*" { /* skip a comment block */ 364 char *comment = skip_comment(); 365 if (IsActiveMode(ReplaceMode)) { 366 fprintf(newfp, "%s", comment); 367 } else { 368 if (IsActiveMode(MsgCommentMode)) { 369 add_comment(MsgCommentMode, comment); 370 } 371 if (IsActiveMode(SetCommentMode)) { 372 add_comment(SetCommentMode, comment); 373 } 374 } 375 free(comment); 376 } 377 378 "//".*\n { /* skip a c++ comment */ 379 if (IsActiveMode(ReplaceMode)) { 380 fprintf(newfp, "%s", yytext); 381 } else { 382 if (IsActiveMode(MsgCommentMode)) { 383 add_comment(MsgCommentMode, yytext); 384 } 385 if (IsActiveMode(SetCommentMode)) { 386 add_comment(SetCommentMode, yytext); 387 } 388 } 389 lineno++; 390 } 391 392 \" { /* skip quoted string */ 393 char *qstr = skip_quoted('"'); 394 if (IsActiveMode(ReplaceMode)) { 395 fprintf(newfp, "\"%s\"", qstr); 396 } 397 free(qstr); 398 } 399 400 \' { /* skip single-quoted character */ 401 char *qchr = skip_quoted('\''); 402 if (IsActiveMode(ReplaceMode)) { 403 fprintf(newfp, "\'%s\'", qchr); 404 } 405 free(qchr); 406 } 407 408 \n { 409 if (IsActiveMode(ReplaceMode)) { 410 fprintf(newfp, "\n"); 411 } 412 lineno++; 413 } 414 415 . { 416 if (IsActiveMode(ReplaceMode)) { 417 fprintf(newfp, "%c", yytext[0]); 418 } 419 } 420 421 %% 422 423 static char * 424 skip_quoted(int skip_ch) 425 { 426 char *buf, *ptr; /* saved buffer and its pointer */ 427 int bsize = BUFSIZ; /* growing buffer size */ 428 int i = 0; /* counter */ 429 int c, old = 0; /* input character */ 430 431 if ((buf = ptr = (char *) malloc(bsize)) == NULL) { 432 prg_err(gettext("fatal: out of memory")); 433 exit(EXIT_FAILURE); 434 } 435 for (;; i++) { 436 if (i == bsize) { 437 bsize += BUFSIZ; 438 if ((buf = (char *) realloc((void *) buf, 439 bsize)) == NULL) { 440 prg_err(gettext("fatal: out of memory")); 441 exit(EXIT_FAILURE); 442 } 443 ptr = buf + i; 444 } 445 c = input(); 446 if (c == skip_ch && old != '\\') { 447 break; 448 } else if (c == '\n') { 449 lineno++; 450 } else if (c == 0) { 451 if (skip_ch == '"') { 452 warning(gettext("warning: unmatched \"")); 453 } else if (skip_ch == '\'') { 454 warning(gettext("warning: unmatched '")); 455 } else { 456 /* Should not happen */ 457 warning(gettext("warning: unmatched \ 458 character")); 459 } 460 break; 461 } 462 *ptr++ = c; 463 if (old == '\\') { 464 old = '\0'; 465 } else { 466 old = c; 467 } 468 } 469 *ptr = '\0'; 470 return buf; 471 } 472 473 static char * 474 skip_comment(void) 475 { 476 char *buf, *ptr; /* saved buffer and its pointer */ 477 int bsize = BUFSIZ; /* growing buffer size */ 478 int i = 0; /* counter */ 479 int c, old = 0; /* input character */ 480 481 if ((buf = ptr = (char *) malloc(bsize)) == NULL) { 482 prg_err(gettext("fatal: out of memory")); 483 exit(EXIT_FAILURE); 484 } 485 *ptr++ = '/'; i++; 486 *ptr++ = '*'; i++; 487 for (;; i++) { 488 if (i == bsize) { 489 bsize += BUFSIZ; 490 if ((buf = (char *) realloc((void *) buf, 491 bsize)) == NULL) { 492 prg_err(gettext("fatal: out of memory")); 493 exit(EXIT_FAILURE); 494 } 495 ptr = buf + i; 496 } 497 c = input(); 498 if (c == '/' && old == '*') { 499 *ptr++ = c; 500 break; 501 } else if (c == '\n') { 502 lineno++; 503 } else if (c == 0) { 504 warning(gettext("warning: unmatched /*")); 505 break; 506 } 507 *ptr++ = old = c; 508 } 509 *ptr = '\0'; 510 return buf; 511 } 512 513 /* 514 * parse_cppline() parses the line control information that a C 515 * preprocessor generates to indicate the location in the original 516 * file. See the cpp man in the details. 517 */ 518 static void 519 parse_cppline(char *str) 520 { 521 int n, line, len; 522 char ch; 523 char file[LINE_MAX]; 524 char *pfile = &file[0]; 525 526 n = sscanf(str, "%c%d%s", &ch, &line, file); 527 528 /* 'file' is a quoted string but 'srcfile' is not. */ 529 len = strlen(file) - 2; 530 pfile++; 531 if (n == 3 && (strncmp(pfile, srcfile, len) == 0)) { 532 pound_is_mine = TRUE; 533 lineno = line - 1; 534 } else if (n == 2 && (pound_is_mine == TRUE)) { 535 lineno = line - 1; 536 } else { 537 pound_is_mine = FALSE; 538 } 539 } 540 541 typedef struct { 542 int line; 543 int msgid; 544 } LineMsgID; 545 546 static LineMsgID line_msgid[NL_MSGMAX]; 547 static int line_msgcnt; 548 549 void 550 init_lex(void) 551 { 552 lineno = 1; 553 end_of_cat = TRUE; 554 pound_is_mine = FALSE; 555 } 556 557 void 558 init_linemsgid(void) 559 { 560 line_msgcnt = 0; 561 memset(line_msgid, 0, sizeof(LineMsgID) * NL_MSGMAX); 562 } 563 564 void 565 set_linemsgid(int line, int msgid) 566 { 567 if (line_msgcnt >= NL_MSGMAX) { 568 return; /* oops */ 569 } 570 line_msgid[line_msgcnt].line = line; 571 line_msgid[line_msgcnt].msgid = msgid; 572 line_msgcnt++; 573 } 574 575 int 576 get_linemsgid(int line) 577 { 578 register int i, left, right; 579 left = 0; 580 right = line_msgcnt - 1; 581 while (left <= right) { 582 i = (left + right) >> 1; 583 if ( line < line_msgid[i].line) { 584 right = i - 1; 585 } else if (line > line_msgid[i].line) { 586 left = i + 1; 587 } else { 588 return line_msgid[i].msgid; 589 } 590 } 591 return NOLINEMSG; 592 } 593 594 void 595 yyerror(char *s) 596 { 597 if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) || 598 IsActiveMode(ReplaceMode)) { 599 return; 600 } 601 src_err(srcfile, lineno, gettext("%s before or at: %s"), s, yytext); 602 } 603 604 void 605 warning(char *s) 606 { 607 if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) || 608 IsActiveMode(ReplaceMode)) { 609 return; 610 } 611 src_err(srcfile, lineno, "%s", s); 612 } 613