1 /* $NetBSD: input.c,v 1.17 2011/07/18 21:46:15 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 __RCSID("$NetBSD: input.c,v 1.17 2011/07/18 21:46:15 christos Exp $"); 38 #endif /* not lint */ 39 40 #include <stdio.h> 41 #include <ctype.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "error.h" 45 46 int cur_wordc; /* how long the current error message is */ 47 char **cur_wordv; /* the actual error message */ 48 49 static Errorclass catchall(void); 50 static Errorclass cpp(void); 51 static Errorclass f77(void); 52 static Errorclass lint0(void); 53 static Errorclass lint1(void); 54 static Errorclass lint2(void); 55 static Errorclass lint3(void); 56 static Errorclass make(void); 57 static Errorclass mod2(void); 58 static Errorclass onelong(void); 59 static Errorclass pccccom(void); /* Portable C Compiler C Compiler */ 60 static Errorclass ri(void); 61 static Errorclass richieccom(void); /* Richie Compiler for 11 */ 62 static Errorclass gcc45ccom(void); /* gcc45+ */ 63 static Errorclass troff(void); 64 65 /* 66 * Eat all of the lines in the input file, attempting to categorize 67 * them by their various flavors 68 */ 69 void 70 eaterrors(int *r_errorc, Eptr **r_errorv) 71 { 72 Errorclass errorclass = C_SYNC; 73 char *line; 74 const char *inbuffer; 75 size_t inbuflen; 76 77 for (;;) { 78 if ((inbuffer = fgetln(errorfile, &inbuflen)) == NULL) 79 break; 80 line = Calloc(inbuflen + 1, sizeof(char)); 81 memcpy(line, inbuffer, inbuflen); 82 line[inbuflen] = '\0'; 83 wordvbuild(line, &cur_wordc, &cur_wordv); 84 85 /* 86 * for convenience, convert cur_wordv to be 1 based, instead 87 * of 0 based. 88 */ 89 cur_wordv -= 1; 90 if (cur_wordc > 0 && 91 ((( errorclass = onelong() ) != C_UNKNOWN) 92 || (( errorclass = cpp() ) != C_UNKNOWN) 93 || (( errorclass = gcc45ccom() ) != C_UNKNOWN) 94 || (( errorclass = pccccom() ) != C_UNKNOWN) 95 || (( errorclass = richieccom() ) != C_UNKNOWN) 96 || (( errorclass = lint0() ) != C_UNKNOWN) 97 || (( errorclass = lint1() ) != C_UNKNOWN) 98 || (( errorclass = lint2() ) != C_UNKNOWN) 99 || (( errorclass = lint3() ) != C_UNKNOWN) 100 || (( errorclass = make() ) != C_UNKNOWN) 101 || (( errorclass = f77() ) != C_UNKNOWN) 102 || ((errorclass = pi() ) != C_UNKNOWN) 103 || (( errorclass = ri() )!= C_UNKNOWN) 104 || (( errorclass = mod2() )!= C_UNKNOWN) 105 || (( errorclass = troff() )!= C_UNKNOWN)) 106 ) ; 107 else 108 errorclass = catchall(); 109 if (cur_wordc) 110 erroradd(cur_wordc, cur_wordv+1, errorclass, C_UNKNOWN); 111 } 112 #ifdef FULLDEBUG 113 printf("%d errorentrys\n", nerrors); 114 #endif 115 arrayify(r_errorc, r_errorv, er_head); 116 } 117 118 /* 119 * create a new error entry, given a zero based array and count 120 */ 121 void 122 erroradd(int errorlength, char **errorv, Errorclass errorclass, 123 Errorclass errorsubclass) 124 { 125 Eptr newerror; 126 const char *cp; 127 128 if (errorclass == C_TRUE) { 129 /* check canonicalization of the second argument*/ 130 for (cp = errorv[1]; *cp && isdigit((unsigned char)*cp); cp++) 131 continue; 132 errorclass = (*cp == '\0') ? C_TRUE : C_NONSPEC; 133 #ifdef FULLDEBUG 134 if (errorclass != C_TRUE) 135 printf("The 2nd word, \"%s\" is not a number.\n", 136 errorv[1]); 137 #endif 138 } 139 if (errorlength > 0) { 140 newerror = Calloc(1, sizeof(Edesc)); 141 newerror->error_language = language; /* language is global */ 142 newerror->error_text = errorv; 143 newerror->error_lgtext = errorlength; 144 if (errorclass == C_TRUE) 145 newerror->error_line = atoi(errorv[1]); 146 newerror->error_e_class = errorclass; 147 newerror->error_s_class = errorsubclass; 148 switch (newerror->error_e_class = discardit(newerror)) { 149 case C_SYNC: nsyncerrors++; break; 150 case C_DISCARD: ndiscard++; break; 151 case C_NULLED: nnulled++; break; 152 case C_NONSPEC: nnonspec++; break; 153 case C_THISFILE: nthisfile++; break; 154 case C_TRUE: ntrue++; break; 155 case C_UNKNOWN: nunknown++; break; 156 case C_IGNORE: nignore++; break; 157 } 158 newerror->error_next = er_head; 159 er_head = newerror; 160 newerror->error_no = nerrors++; 161 } /* length > 0 */ 162 } 163 164 static Errorclass 165 onelong(void) 166 { 167 char **nwordv; 168 169 if (cur_wordc == 1 && language != INLD) { 170 /* 171 * We have either: 172 * a) file name from cc 173 * b) Assembler telling world that it is complaining 174 * c) Noise from make ("Stop.") 175 * c) Random noise 176 */ 177 cur_wordc = 0; 178 if (strcmp(cur_wordv[1], "Stop.") == 0) { 179 language = INMAKE; 180 return (C_SYNC); 181 } 182 if (strcmp(cur_wordv[1], "Assembler:") == 0) { 183 /* assembler always alerts us to what happened*/ 184 language = INAS; 185 return (C_SYNC); 186 } else 187 if (strcmp(cur_wordv[1], "Undefined:") == 0) { 188 /* loader complains about unknown symbols*/ 189 language = INLD; 190 return (C_SYNC); 191 } 192 if (lastchar(cur_wordv[1]) == ':') { 193 /* cc tells us what file we are in */ 194 currentfilename = cur_wordv[1]; 195 (void)substitute(currentfilename, ':', '\0'); 196 language = INCC; 197 return (C_SYNC); 198 } 199 } else 200 if (cur_wordc == 1 && language == INLD) { 201 nwordv = Calloc(4, sizeof(char *)); 202 nwordv[0] = Strdup("ld:"); /* XXX leaked */ 203 nwordv[1] = cur_wordv[1]; 204 nwordv[2] = Strdup("is"); /* XXX leaked */ 205 nwordv[3] = Strdup("undefined.");/* XXX leaked */ 206 cur_wordc = 4; 207 cur_wordv = nwordv - 1; 208 return (C_NONSPEC); 209 } else 210 if (cur_wordc == 1) { 211 return (C_SYNC); 212 } 213 return (C_UNKNOWN); 214 } /* end of one long */ 215 216 static Errorclass 217 cpp(void) 218 { 219 /* 220 * Now attempt a cpp error message match 221 * Examples: 222 * ./morse.h: 23: undefined control 223 * morsesend.c: 229: MAGNIBBL: argument mismatch 224 * morsesend.c: 237: MAGNIBBL: argument mismatch 225 * test1.c: 6: undefined control 226 */ 227 if (cur_wordc < 3) 228 return (C_UNKNOWN); 229 if (language != INLD /* loader errors have almost same fmt */ 230 && lastchar(cur_wordv[1]) == ':' 231 && isdigit((unsigned char)firstchar(cur_wordv[2])) 232 && lastchar(cur_wordv[2]) == ':') { 233 language = INCPP; 234 clob_last(cur_wordv[1], '\0'); 235 clob_last(cur_wordv[2], '\0'); 236 return (C_TRUE); 237 } 238 return (C_UNKNOWN); 239 } /*end of cpp*/ 240 241 static Errorclass 242 pccccom(void) 243 { 244 /* 245 * Now attempt a ccom error message match: 246 * Examples: 247 * "morsesend.c", line 237: operands of & have incompatible types 248 * "test.c", line 7: warning: old-fashioned initialization: use = 249 * "subdir.d/foo2.h", line 1: illegal initialization 250 */ 251 if (cur_wordc < 4) 252 return (C_UNKNOWN); 253 if (firstchar(cur_wordv[1]) == '"' 254 && lastchar(cur_wordv[1]) == ',' 255 && next_lastchar(cur_wordv[1]) == '"' 256 && strcmp(cur_wordv[2], "line") == 0 257 && isdigit((unsigned char)firstchar(cur_wordv[3])) 258 && lastchar(cur_wordv[3]) == ':') { 259 clob_last(cur_wordv[1], '\0'); /* drop last , */ 260 clob_last(cur_wordv[1], '\0'); /* drop last " */ 261 cur_wordv[1]++; /* drop first " */ 262 clob_last(cur_wordv[3], '\0'); /* drop : on line number */ 263 cur_wordv[2] = cur_wordv[1]; /* overwrite "line" */ 264 cur_wordv++; /*compensate*/ 265 cur_wordc--; 266 currentfilename = cur_wordv[1]; 267 language = INCC; 268 return (C_TRUE); 269 } 270 return (C_UNKNOWN); 271 } /* end of ccom */ 272 273 /* 274 * Do the error message from gcc 4.5+ which prints: 275 * 276 * fprintf(stderr, "%s:%d:%d: ", filename, line, column); 277 */ 278 279 static Errorclass 280 gcc45ccom(void) 281 { 282 char *cp, *ccp; 283 char **nwordv; 284 char *file; 285 286 if (cur_wordc < 2) 287 return C_UNKNOWN; 288 289 if (lastchar(cur_wordv[1]) != ':') 290 return C_UNKNOWN; 291 292 cp = cur_wordv[1] + strlen(cur_wordv[1]) - 1; 293 while (isdigit((unsigned char)*--cp)) 294 continue; 295 if (*cp != ':') 296 return C_UNKNOWN; 297 298 ccp = cp; 299 while (isdigit((unsigned char)*--cp)) 300 continue; 301 if (*cp != ':') 302 return C_UNKNOWN; 303 304 clob_last(cur_wordv[1], '\0'); /* last : */ 305 *ccp = '\0'; /* middle : */ 306 *cp = '\0'; /* first : */ 307 file = cur_wordv[1]; 308 #ifdef notyet 309 #define EHEAD 2 310 #else 311 #define EHEAD 1 /* Nothing to do with column info yet */ 312 #endif 313 nwordv = wordvsplice(EHEAD, cur_wordc, cur_wordv + 1); 314 nwordv[0] = file; 315 nwordv[1] = cp + 1; 316 #ifdef notyet 317 nwordv[2] = ccp + 1; 318 #endif 319 cur_wordc += 1; 320 cur_wordv = nwordv - 1; 321 language = INCC; 322 currentfilename = cur_wordv[1]; 323 return C_TRUE; 324 } 325 326 /* 327 * Do the error message from the Richie C Compiler for the PDP11, 328 * which has this source: 329 * 330 * if (filename[0]) 331 * fprintf(stderr, "%s:", filename); 332 * fprintf(stderr, "%d: ", line); 333 * 334 */ 335 336 static Errorclass 337 richieccom(void) 338 { 339 char *cp; 340 char **nwordv; 341 char *file; 342 343 if (cur_wordc < 2) 344 return (C_UNKNOWN); 345 346 if (lastchar(cur_wordv[1]) == ':') { 347 cp = cur_wordv[1] + strlen(cur_wordv[1]) - 1; 348 while (isdigit((unsigned char)*--cp)) 349 continue; 350 if (*cp == ':') { 351 clob_last(cur_wordv[1], '\0'); /* last : */ 352 *cp = '\0'; /* first : */ 353 file = cur_wordv[1]; 354 nwordv = wordvsplice(1, cur_wordc, cur_wordv+1); 355 nwordv[0] = file; 356 nwordv[1] = cp + 1; 357 cur_wordc += 1; 358 cur_wordv = nwordv - 1; 359 language = INCC; 360 currentfilename = cur_wordv[1]; 361 return (C_TRUE); 362 } 363 } 364 return (C_UNKNOWN); 365 } 366 367 static Errorclass 368 lint0(void) 369 { 370 char **nwordv; 371 char *line, *file; 372 373 /* 374 * Attempt a match for the new lint style normal compiler 375 * error messages, of the form 376 * 377 * printf("%s(%d): %s\n", filename, linenumber, message); 378 */ 379 if (cur_wordc < 2) 380 return (C_UNKNOWN); 381 382 if (lastchar(cur_wordv[1]) == ':' 383 && next_lastchar(cur_wordv[1]) == ')') { 384 clob_last(cur_wordv[1], '\0'); /* colon */ 385 if (persperdexplode(cur_wordv[1], &line, &file)) { 386 nwordv = wordvsplice(1, cur_wordc, cur_wordv+1); 387 nwordv[0] = file; /* file name */ 388 nwordv[1] = line; /* line number */ 389 cur_wordc += 1; 390 cur_wordv = nwordv - 1; 391 language = INLINT; 392 return (C_TRUE); 393 } 394 cur_wordv[1][strlen(cur_wordv[1])] = ':'; 395 } 396 return (C_UNKNOWN); 397 } 398 399 static Errorclass 400 lint1(void) 401 { 402 char *line1 = NULL, *line2 = NULL; 403 char *file1 = NULL, *file2 = NULL; 404 char **nwordv1, **nwordv2; 405 406 /* 407 * Now, attempt a match for the various errors that lint 408 * can complain about. 409 * 410 * Look first for type 1 lint errors 411 */ 412 if (cur_wordc > 1 && strcmp(cur_wordv[cur_wordc-1], "::") == 0) { 413 /* 414 * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d) 415 * %.7s value used inconsistently %s(%d) :: %s(%d) 416 * %.7s multiply declared %s(%d) :: %s(%d) 417 * %.7s value declared inconsistently %s(%d) :: %s(%d) 418 * %.7s function value type must be declared before use %s(%d) :: %s(%d) 419 */ 420 language = INLINT; 421 if (cur_wordc > 2 422 && persperdexplode(cur_wordv[cur_wordc], &line2, &file2) 423 && persperdexplode(cur_wordv[cur_wordc-2], &line1, &file1)) { 424 nwordv1 = wordvsplice(2, cur_wordc, cur_wordv+1); 425 nwordv2 = wordvsplice(2, cur_wordc, cur_wordv+1); 426 nwordv1[0] = file1; 427 nwordv1[1] = line1; 428 erroradd(cur_wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/ 429 nwordv2[0] = file2; 430 nwordv2[1] = line2; 431 cur_wordc = cur_wordc + 2; 432 cur_wordv = nwordv2 - 1; /* 1 based */ 433 return (C_TRUE); 434 } 435 } 436 if (file2) 437 free(file2); 438 if (file1) 439 free(file1); 440 if (line2) 441 free(line2); 442 if (line1) 443 free(line1); 444 return (C_UNKNOWN); 445 } /* end of lint 1*/ 446 447 static Errorclass 448 lint2(void) 449 { 450 char *file; 451 char *line; 452 char **nwordv; 453 454 /* 455 * Look for type 2 lint errors 456 * 457 * %.7s used( %s(%d) ), but not defined 458 * %.7s defined( %s(%d) ), but never used 459 * %.7s declared( %s(%d) ), but never used or defined 460 * 461 * bufp defined( "./metric.h"(10) ), but never used 462 */ 463 if (cur_wordc < 5) 464 return (C_UNKNOWN); 465 466 if (lastchar(cur_wordv[2]) == '(' /* ')' */ 467 && strcmp(cur_wordv[4], "),") == 0) { 468 language = INLINT; 469 if (persperdexplode(cur_wordv[3], &line, &file)) { 470 nwordv = wordvsplice(2, cur_wordc, cur_wordv+1); 471 nwordv[0] = file; 472 nwordv[1] = line; 473 cur_wordc = cur_wordc + 2; 474 cur_wordv = nwordv - 1; /* 1 based */ 475 return (C_TRUE); 476 } 477 } 478 return (C_UNKNOWN); 479 } /* end of lint 2*/ 480 481 #if 0 /* not const-correct */ 482 static char *Lint31[4] = {"returns", "value", "which", "is"}; 483 static char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"}; 484 #else 485 DECL_STRINGS_4(static, Lint31, 486 "returns", "value", "which", "is"); 487 DECL_STRINGS_6(static, Lint32, 488 "value", "is", "used,", "but", "none", "returned"); 489 #endif 490 491 static Errorclass 492 lint3(void) 493 { 494 if (cur_wordc < 3) 495 return (C_UNKNOWN); 496 if (wordvcmp(cur_wordv+2, 4, Lint31) == 0 497 || wordvcmp(cur_wordv+2, 6, Lint32) == 0) { 498 language = INLINT; 499 return (C_NONSPEC); 500 } 501 return (C_UNKNOWN); 502 } 503 504 /* 505 * Special word vectors for use by F77 recognition 506 */ 507 #if 0 /* not const-correct */ 508 static char *F77_fatal[3] = {"Compiler", "error", "line"}; 509 static char *F77_error[3] = {"Error", "on", "line"}; 510 static char *F77_warning[3] = {"Warning", "on", "line"}; 511 static char *F77_no_ass[3] = {"Error.","No","assembly."}; 512 #else 513 DECL_STRINGS_3(static, F77_fatal, "Compiler", "error", "line"); 514 DECL_STRINGS_3(static, F77_error, "Error", "on", "line"); 515 DECL_STRINGS_3(static, F77_warning, "Warning", "on", "line"); 516 DECL_STRINGS_3(static, F77_no_ass, "Error.", "No", "assembly."); 517 #endif 518 519 static Errorclass 520 f77(void) 521 { 522 char **nwordv; 523 524 /* 525 * look for f77 errors: 526 * Error messages from /usr/src/cmd/f77/error.c, with 527 * these printf formats: 528 * 529 * Compiler error line %d of %s: %s 530 * Error on line %d of %s: %s 531 * Warning on line %d of %s: %s 532 * Error. No assembly. 533 */ 534 if (cur_wordc == 3 && wordvcmp(cur_wordv+1, 3, F77_no_ass) == 0) { 535 cur_wordc = 0; 536 return (C_SYNC); 537 } 538 if (cur_wordc < 6) 539 return (C_UNKNOWN); 540 if (lastchar(cur_wordv[6]) == ':' 541 && ( 542 wordvcmp(cur_wordv+1, 3, F77_fatal) == 0 543 || wordvcmp(cur_wordv+1, 3, F77_error) == 0 544 || wordvcmp(cur_wordv+1, 3, F77_warning) == 0 545 ) 546 ) { 547 language = INF77; 548 nwordv = wordvsplice(2, cur_wordc, cur_wordv+1); 549 nwordv[0] = cur_wordv[6]; 550 clob_last(nwordv[0],'\0'); 551 nwordv[1] = cur_wordv[4]; 552 cur_wordc += 2; 553 cur_wordv = nwordv - 1; /* 1 based */ 554 return (C_TRUE); 555 } 556 return (C_UNKNOWN); 557 } /* end of f77 */ 558 559 #if 0 /* not const-correct */ 560 static char *Make_Croak[3] = {"***", "Error", "code"}; 561 static char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"}; 562 #else 563 DECL_STRINGS_3(static, Make_Croak, "***", "Error", "code"); 564 DECL_STRINGS_5(static, Make_NotRemade, 565 "not", "remade", "because", "of", "errors"); 566 #endif 567 568 static Errorclass 569 make(void) 570 { 571 if (wordvcmp(cur_wordv+1, 3, Make_Croak) == 0) { 572 language = INMAKE; 573 return (C_SYNC); 574 } 575 if (wordvcmp(cur_wordv+2, 5, Make_NotRemade) == 0) { 576 language = INMAKE; 577 return (C_SYNC); 578 } 579 return (C_UNKNOWN); 580 } 581 582 static Errorclass 583 ri(void) 584 { 585 /* 586 * Match an error message produced by ri; here is the 587 * procedure yanked from the distributed version of ri 588 * April 24, 1980. 589 * 590 * serror(str, x1, x2, x3) 591 * char str[]; 592 * char *x1, *x2, *x3; 593 * { 594 * extern int yylineno; 595 * 596 * putc('"', stdout); 597 * fputs(srcfile, stdout); 598 * putc('"', stdout); 599 * fprintf(stdout, " %d: ", yylineno); 600 * fprintf(stdout, str, x1, x2, x3); 601 * fprintf(stdout, "\n"); 602 * synerrs++; 603 * } 604 */ 605 if (cur_wordc < 3) 606 return (C_UNKNOWN); 607 if (firstchar(cur_wordv[1]) == '"' 608 && lastchar(cur_wordv[1]) == '"' 609 && lastchar(cur_wordv[2]) == ':' 610 && isdigit((unsigned char)firstchar(cur_wordv[2]))) { 611 clob_last(cur_wordv[1], '\0'); /* drop the last " */ 612 cur_wordv[1]++; /* skip over the first " */ 613 clob_last(cur_wordv[2], '\0'); 614 language = INRI; 615 return (C_TRUE); 616 } 617 return (C_UNKNOWN); 618 } 619 620 static Errorclass 621 catchall(void) 622 { 623 /* 624 * Catches random things. 625 */ 626 language = INUNKNOWN; 627 return (C_NONSPEC); 628 } /* end of catch all*/ 629 630 static Errorclass 631 troff(void) 632 { 633 /* 634 * troff source error message, from eqn, bib, tbl... 635 * Just like pcc ccom, except uses `' 636 */ 637 if (cur_wordc < 4) 638 return (C_UNKNOWN); 639 640 if (firstchar(cur_wordv[1]) == '`' 641 && lastchar(cur_wordv[1]) == ',' 642 && next_lastchar(cur_wordv[1]) == '\'' 643 && strcmp(cur_wordv[2], "line") == 0 644 && isdigit((unsigned char)firstchar(cur_wordv[3])) 645 && lastchar(cur_wordv[3]) == ':') { 646 clob_last(cur_wordv[1], '\0'); /* drop last , */ 647 clob_last(cur_wordv[1], '\0'); /* drop last " */ 648 cur_wordv[1]++; /* drop first " */ 649 clob_last(cur_wordv[3], '\0'); /* drop : on line number */ 650 cur_wordv[2] = cur_wordv[1]; /* overwrite "line" */ 651 cur_wordv++; /*compensate*/ 652 currentfilename = cur_wordv[1]; 653 language = INTROFF; 654 return (C_TRUE); 655 } 656 return (C_UNKNOWN); 657 } 658 659 static Errorclass 660 mod2(void) 661 { 662 /* 663 * for decwrl modula2 compiler (powell) 664 */ 665 if (cur_wordc < 5) 666 return (C_UNKNOWN); 667 if ((strcmp(cur_wordv[1], "!!!") == 0 /* early version */ 668 || strcmp(cur_wordv[1], "File") == 0) /* later version */ 669 && lastchar(cur_wordv[2]) == ',' /* file name */ 670 && strcmp(cur_wordv[3], "line") == 0 671 && isdigit((unsigned char)firstchar(cur_wordv[4])) /* line number */ 672 && lastchar(cur_wordv[4]) == ':' /* line number */ 673 ) { 674 clob_last(cur_wordv[2], '\0'); /* drop last , on file name */ 675 clob_last(cur_wordv[4], '\0'); /* drop last : on line number */ 676 cur_wordv[3] = cur_wordv[2]; /* file name on top of "line" */ 677 cur_wordv += 2; 678 cur_wordc -= 2; 679 currentfilename = cur_wordv[1]; 680 language = INMOD2; 681 return (C_TRUE); 682 } 683 return (C_UNKNOWN); 684 } 685