GnuCOBOL  2.0
A free COBOL compiler
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
pplex.l File Reference
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "cobc.h"
#include "ppparse.h"
Include dependency graph for pplex.l:

Macros

#define YY_READ_BUF_SIZE   32768
 
#define YY_BUF_SIZE   32768
 
#define YY_SKIP_YYWRAP
 
#define ppwrap()   1
 
#define PPLEX_BUFF_LEN   512
 
#define YY_INPUT(buf, result, max_size)   result = ppinput (buf, max_size);
 
#define ECHO   fputs (yytext, yyout)
 
#define YY_USER_INIT
 
#define COB_IN_PPLEX   1
 
#define PLEX_COND_DEPTH   16
 

Functions

 yy_switch_to_buffer (buffer)
 
static int ppinput (char *buff, const size_t max_size)
 
static struct cb_text_listpp_text_list_add (struct cb_text_list *list, const char *text, const size_t size)
 
static void ppecho (const char *text, const cob_u32_t alt_space, const int textlen)
 
static void skip_to_eol (void)
 
static void display_to_eol (void)
 
static void check_comments (const char *keyword, const char *text)
 
static void check_listing (const char *text, const unsigned int comment)
 

Variables

option option case insensitive
option never interactive
option 
prefix
 

Macro Definition Documentation

#define COB_IN_PPLEX   1
#define ECHO   fputs (yytext, yyout)
#define PLEX_COND_DEPTH   16
#define PPLEX_BUFF_LEN   512
#define ppwrap ( )    1
#define YY_BUF_SIZE   32768
#define YY_INPUT (   buf,
  result,
  max_size 
)    result = ppinput (buf, max_size);
#define YY_READ_BUF_SIZE   32768
#define YY_SKIP_YYWRAP
#define YY_USER_INIT
Value:
if (!plexbuff1) { \
plexbuff1 = cobc_malloc ((size_t)COB_SMALL_BUFF); \
} \
if (!plexbuff2) { \
plexbuff2 = cobc_malloc ((size_t)COB_SMALL_BUFF); \
} \
requires_listing_line = 1; \
comment_allowed = 1;

Function Documentation

static void check_comments ( const char *  keyword,
const char *  text 
)
static

References cb_verify(), comment_allowed, ppecho(), skip_to_eol(), within_comment, and yyleng.

1620 {
1621  /* Treated as comments when in Identification Division */
1622  if (comment_allowed) {
1623  cb_verify (cb_author_paragraph, keyword);
1624  /* Skip comments until the end of line */
1625  within_comment = 1;
1626  skip_to_eol ();
1627  } else {
1628  ppecho (text, 0, yyleng);
1629  }
1630 }
static void check_listing ( const char *  text,
const unsigned int  comment 
)
static

References CB_FORMAT_FIXED, cb_listing_file, cb_source_format, cobc_gen_listing, listing_line, requires_listing_line, requires_new_line, and cb_text_list::text.

Referenced by ppecho().

1634 {
1635  const char *s;
1636  char c;
1637 
1638  /* Check for listing */
1639  if (!cb_listing_file) {
1640  /* Nothing to do */
1641  return;
1642  }
1643  if (!text) {
1644  return;
1645  }
1646  if (cobc_gen_listing > 1) {
1647  /* Passed to cobxref */
1648  fputs (text, cb_listing_file);
1649  return;
1650  }
1651  if (comment) {
1652  c = '*';
1653  } else {
1654  c = ' ';
1655  }
1656 
1657  if (requires_listing_line) {
1658  if (requires_new_line) {
1659  requires_new_line = 0;
1660  putc ('\n', cb_listing_file);
1661  }
1662  fprintf (cb_listing_file, "%6d%c", ++listing_line, c);
1663  }
1664 
1665  if (requires_listing_line && cb_source_format == CB_FORMAT_FIXED &&
1666  strlen (text) > 6) {
1667  s = &text[6];
1668  } else {
1669  s = text;
1670  }
1671  fputs (s, cb_listing_file);
1672  if (strchr (text, '\n')) {
1674  } else {
1676  }
1677 }
static void display_to_eol ( void  )
static

References input(), plex_skip_input, and unput.

1599 {
1600  int c;
1601 
1602  while ((c = input ()) != EOF) {
1603  if (c == '\n') {
1604  break;
1605  }
1606  if (!plex_skip_input) {
1607  putchar (c);
1608  }
1609  }
1610  if (!plex_skip_input) {
1611  putchar ('\n');
1612  }
1613  if (c != EOF) {
1614  unput (c);
1615  }
1616 }
static struct cb_text_list* pp_text_list_add ( struct cb_text_list list,
const char *  text,
const size_t  size 
)
staticread

References cobc_plex_malloc(), cb_text_list::last, cb_text_list::next, p, and cb_text_list::text.

Referenced by ppecho().

1415 {
1416  struct cb_text_list *p;
1417  void *tp;
1418 
1419  p = cobc_plex_malloc (sizeof (struct cb_text_list));
1420  tp = cobc_plex_malloc (size + 1);
1421  memcpy (tp, text, size);
1422  p->text = tp;
1423  if (!list) {
1424  p->last = p;
1425  return p;
1426  }
1427  list->last->next = p;
1428  list->last = p;
1429  return list;
1430 }
static void ppecho ( const char *  text,
const cob_u32_t  alt_space,
const int  textlen 
)
static

References base_replace_list, cb_listing_file, CB_REPLACE_LEADING, CB_REPLACE_TRAILING, check_listing(), cobc_free(), cobc_strdup(), current_replace_list, cb_replace_list::last, cb_replace_list::lead_trail, cb_replace_list::new_text, cb_text_list::next, cb_replace_list::next, NULL, cb_replace_list::old_text, pp_text_list_add(), ppout, cb_text_list::text, text_queue, and yytext.

Referenced by check_comments().

1434 {
1435  struct cb_replace_list *r;
1436  struct cb_replace_list *save_ptr;
1437  const struct cb_text_list *lno;
1438  struct cb_text_list *queue;
1439  struct cb_text_list *save_queue;
1440  const char *s;
1441  char *temp_ptr;
1442  size_t size;
1443  size_t size2;
1444 
1445  /* Check for replacement text before outputting */
1446  if (alt_space) {
1447  s = yytext;
1448  } else {
1449  s = text;
1450  }
1451 
1452  if (text_queue == NULL && (text[0] == ' ' || text[0] == '\n')) {
1453  /* No replacement */
1454  fwrite (text, (size_t)textlen, (size_t)1, ppout);
1455  if (cb_listing_file) {
1456  check_listing (s, 0);
1457  }
1458  return;
1459  }
1461  /* Ouput queue */
1462  for (; text_queue; text_queue = text_queue->next) {
1463  fputs (text_queue->text, ppout);
1464  }
1465  fwrite (text, (size_t)textlen, (size_t)1, ppout);
1466  if (cb_listing_file) {
1467  check_listing (s, 0);
1468  }
1469  return;
1470  }
1471  if (!current_replace_list) {
1473  save_ptr = NULL;
1474  } else {
1476  save_ptr = current_replace_list->last;
1477  }
1478 
1479  /* Do replacement */
1480  text_queue = pp_text_list_add (text_queue, text, (size_t)textlen);
1481 
1482  save_queue = NULL;
1483  size = 0;
1484  size2 = 0;
1485  for (r = current_replace_list; r; r = r->next) {
1486  queue = text_queue;
1487  /* The LEADING/TRAILING code looks peculiar as we use */
1488  /* variables after breaking out of the loop BUT */
1489  /* ppparse.y guarantees that we have only one token */
1490  /* and therefore only one iteration of this loop */
1491  for (lno = r->old_text; lno; lno = lno->next) {
1492  if (lno->text[0] == ' ' || lno->text[0] == '\n') {
1493  continue;
1494  }
1495  while (queue && (queue->text[0] == ' ' ||
1496  queue->text[0] == '\n')) {
1497  queue = queue->next;
1498  }
1499  if (queue == NULL) {
1500  /* Partial match */
1501  if (!save_ptr) {
1503  } else {
1504  save_ptr->next = NULL;
1505  }
1506  return;
1507  }
1508  if (r->lead_trail == CB_REPLACE_LEADING) {
1509  /* Check leading text */
1510  size = strlen (lno->text);
1511  if (strncasecmp (lno->text, queue->text, size)) {
1512  /* No match */
1513  break;
1514  }
1515  save_queue = queue;
1516  } else if (r->lead_trail == CB_REPLACE_TRAILING) {
1517  /* Check trailing text */
1518  size = strlen (lno->text);
1519  size2 = strlen (queue->text);
1520  if (size2 < size) {
1521  /* No match */
1522  break;
1523  }
1524  size2 -= size;
1525  if (strncasecmp (lno->text, queue->text + size2, size)) {
1526  /* No match */
1527  break;
1528  }
1529  save_queue = queue;
1530  } else if (strcasecmp (lno->text, queue->text)) {
1531  /* No match */
1532  break;
1533  }
1534  queue = queue->next;
1535  }
1536  if (lno == NULL) {
1537  /* Match */
1538  if (r->lead_trail == CB_REPLACE_TRAILING) {
1539  /* Non-matched part of original text */
1540  fprintf (ppout, "%*.*s", (int)size2, (int)size2,
1541  save_queue->text);
1542  if (cb_listing_file) {
1543  temp_ptr = cobc_strdup (save_queue->text);
1544  *(temp_ptr + size2) = 0;
1545  check_listing (temp_ptr, 0);
1546  cobc_free (temp_ptr);
1547  }
1548  }
1549  for (lno = r->new_text; lno; lno = lno->next) {
1550  fputs (lno->text, ppout);
1551  if (cb_listing_file) {
1552  check_listing (lno->text, 0);
1553  }
1554  }
1555  if (r->lead_trail == CB_REPLACE_LEADING) {
1556  /* Non-matched part of original text */
1557  fputs (save_queue->text + size, ppout);
1558  if (cb_listing_file) {
1559  check_listing (save_queue->text + size, 0);
1560  }
1561  }
1562  text_queue = queue;
1563  continue;
1564  }
1565  }
1566 
1567  /* No match */
1568  for (; text_queue; text_queue = text_queue->next) {
1569  fputs (text_queue->text, ppout);
1570  if (cb_listing_file) {
1572  }
1573  }
1574  if (!save_ptr) {
1576  } else {
1577  save_ptr->next = NULL;
1578  }
1579 }
static int ppinput ( char *  buff,
const size_t  max_size 
)
static

References _, buffer_overflow, CB_FORMAT_FIXED, CB_FORMAT_FREE, cb_plex_error(), cb_plex_warning(), cb_source_format, consecutive_quotation, likely, need_continuation, newline_count, plex_skip_input, ppin, PPLEX_BUFF_LEN, quotation_mark, unlikely, within_comment, and YY_NULL.

1007 {
1008  char *bp;
1009  size_t gotcr;
1010  size_t line_overflow;
1011  size_t continuation;
1012  int ipchar;
1013  int i;
1014  int n;
1015  int coln;
1016 
1017  /* Read line(s) */
1018 
1019  continuation = 0;
1020 start:
1021  if (unlikely(buffer_overflow ||
1022  (newline_count + PPLEX_BUFF_LEN) >= max_size)) {
1023  if (need_continuation || continuation) {
1025  _("Buffer overrun - Too much continuation lines"));
1026  return YY_NULL;
1027  }
1028  if (newline_count < max_size) {
1029  memset (buff, '\n', newline_count);
1030  buff[newline_count] = 0;
1031  ipchar = (int)newline_count;
1032  newline_count = 0;
1033  buffer_overflow = 0;
1034  return ipchar;
1035  }
1036  buffer_overflow = 1;
1037  ipchar = max_size - 1;
1038  memset (buff, '\n', (size_t)ipchar);
1039  buff[ipchar] = 0;
1040  newline_count -= ipchar;
1041  return ipchar;
1042  }
1043  gotcr = 0;
1044  line_overflow = 0;
1045  ipchar = 0;
1046  for (n = 0; ipchar != '\n';) {
1047  if (unlikely(n == PPLEX_BUFF_LEN)) {
1048  if (line_overflow != 2) {
1049  line_overflow = 1;
1050  }
1051  }
1052  ipchar = getc (ppin);
1053  if (unlikely(ipchar == EOF)) {
1054  if (n > 0) {
1055  /* No end of line at end of file */
1056  break;
1057  }
1058  if (newline_count == 0) {
1059  return YY_NULL;
1060  }
1061  memset (buff, '\n', newline_count);
1062  buff[newline_count] = 0;
1063  ipchar = (int)newline_count;
1064  newline_count = 0;
1065  return ipchar;
1066  }
1067 #ifndef COB_EBCDIC_MACHINE
1068  if (unlikely(ipchar == 0x1A && !n)) {
1069  continue;
1070  }
1071 #endif
1072  if (unlikely(gotcr)) {
1073  gotcr = 0;
1074  if (ipchar != '\n') {
1075  if (likely(line_overflow == 0)) {
1076  buff[n++] = '\r';
1077  } else {
1078  line_overflow = 2;
1079  }
1080  }
1081  }
1082  if (unlikely(ipchar == '\r')) {
1083  gotcr = 1;
1084  continue;
1085  }
1086  if (unlikely(ipchar == '\t')) {
1087  if (likely(line_overflow == 0)) {
1088  buff[n++] = ' ';
1089  while (n % cb_tab_width != 0) {
1090  buff[n++] = ' ';
1091  }
1092  if (unlikely(n > PPLEX_BUFF_LEN)) {
1093  n = PPLEX_BUFF_LEN;
1094  }
1095  }
1096  continue;
1097  }
1098  if (likely(line_overflow == 0)) {
1099  buff[n++] = (char)ipchar;
1100  } else if ((char)ipchar != ' ' && (char)ipchar != '\n') {
1101  line_overflow = 2;
1102  }
1103  }
1104 
1105  if (buff[n - 1] != '\n') {
1106  /* FIXME: cb_source_line is one too low when CB_FORMAT_FREE is used
1107  [but only during ppinput() in pplex.l ?] - Workaround for now:
1108  Temporary newline_count + 1
1109  */
1110  if (cb_source_format == CB_FORMAT_FREE) {
1111  if (line_overflow == 0) {
1113  _("Line not terminated by a newline"));
1114  } else if (line_overflow == 2) {
1116  _("Source text exceeds %d bytes, will be truncated"), PPLEX_BUFF_LEN);
1117  }
1118  } else {
1119  if (line_overflow == 0) {
1121  _("Line not terminated by a newline"));
1122  } else if (line_overflow == 2) {
1124  _("Source text exceeds %d bytes, will be truncated"), PPLEX_BUFF_LEN);
1125  }
1126  }
1127  buff[n++] = '\n';
1128  }
1129  buff[n] = 0;
1130 
1131  if (cb_source_format == CB_FORMAT_FIXED) {
1132  if (n < 8) {
1133  /* Line too short */
1134  newline_count++;
1135  goto start;
1136  }
1137 
1138  if (cb_flag_mfcomment) {
1139  if (buff[0] == '*' || buff[0] == '/') {
1140  newline_count++;
1141  goto start;
1142  }
1143  }
1144 
1145  /* Check if text is longer than cb_text_column */
1146  if (n > cb_text_column + 1) {
1147  /* Show warning if it is not whitespace
1148  (postponed after checking for comments by setting
1149  line_overflow to first column that leads to
1150  "source text too long")
1151  */
1152  if (cb_warn_column_overflow && line_overflow == 0) {
1153  for (coln = cb_text_column; coln < n; ++coln) {
1154  if (buff[coln] != ' ' && buff[coln] != '\n') {
1155  line_overflow = coln;
1156  break;
1157  }
1158  }
1159  } else {
1160  line_overflow = 0;
1161  }
1162  /* Remove it */
1163  buff[cb_text_column] = '\n';
1164  buff[cb_text_column + 1] = 0;
1165  n = cb_text_column + 1;
1166  } else {
1167  line_overflow = 0;
1168  }
1169 
1170  memset (buff, ' ', (size_t)6);
1171  /* Note we allow directive lines to start at column 7 */
1172  bp = &buff[6];
1173  } else {
1174  bp = buff;
1175  }
1176 
1177  /* Check for directives/floating comment at first non-space of line */
1178  ipchar = 0;
1179  i = 0;
1180  for (; *bp; bp++) {
1181  if (*bp != ' ') {
1182  if ((*bp == '$' && !(cb_source_format == CB_FORMAT_FIXED && i == 0)) ||
1183  (*bp == '>' && bp[1] == '>' ) ) {
1184  /* Directive */
1185  ipchar = 1;
1186  } else if ((*bp == '*' && bp[1] == '>' ) ||
1187  (cb_flag_acucomment && *bp == '|') ) {
1188  /* Float comment */
1189  newline_count++;
1190  goto start;
1191  }
1192  break;
1193  }
1194  i = 1;
1195  }
1196  if (ipchar) {
1197  /* Directive - pass complete line with NL to ppparse */
1198  if (newline_count) {
1199  /* Move including NL and NULL byte */
1200  memmove (buff + newline_count, buff, (size_t)(n + 1));
1201  memset (buff, '\n', newline_count);
1202  n += newline_count;
1203  newline_count = 0;
1204  }
1205  return n;
1206  }
1207 
1208  if (plex_skip_input) {
1209  /* Skipping input */
1210  newline_count++;
1211  goto start;
1212  }
1213 
1214  /* Return when free format (no floating comments removed!) */
1215  if (cb_source_format == CB_FORMAT_FREE) {
1216  within_comment = 0;
1217  if (newline_count) {
1218  memmove (buff + newline_count, buff, (size_t)(n + 1));
1219  memset (buff, '\n', newline_count);
1220  n += newline_count;
1221  newline_count = 0;
1222  }
1223  return n;
1224  }
1225 
1226  /* Fixed format */
1227 
1228  /* Check the indicator (column 7) */
1229  if (cb_flag_acucomment && buff[6] == '$') {
1230  buff[6] = '*';
1231  }
1232  switch (buff[6]) {
1233  case ' ':
1234  break;
1235  case '-':
1236  if (unlikely(within_comment)) {
1238  _("Invalid continuation in comment entry"));
1239  newline_count++;
1240  goto start;
1241  }
1242  continuation = 1;
1243  break;
1244  case 'd':
1245  case 'D':
1246  /* Debugging line */
1247  if (cb_flag_debugging_line) {
1248  break;
1249  }
1250  newline_count++;
1251  goto start;
1252  case '*':
1253  case '/':
1254  /* Comment line */
1255  newline_count++;
1256  goto start;
1257  default:
1258  /* Invalid indicator */
1260  _("Invalid indicator '%c' at column 7"), buff[6]);
1261  newline_count++;
1262  return YY_NULL;
1263  }
1264 
1265  /* Skip comments that follow after AUTHORS, etc. */
1266  if (unlikely(within_comment)) {
1267  /* Check all of "Area A" */
1268  for (ipchar = 7; ipchar < (n - 1) && ipchar < 11; ++ipchar) {
1269  if (buff[ipchar] != ' ') {
1270  ipchar = 0;
1271  break;
1272  }
1273  }
1274  if (ipchar) {
1275  newline_count++;
1276  goto start;
1277  }
1278  within_comment = 0;
1279  }
1280 
1281  /* Skip blank lines */
1282  for (i = 7; buff[i] == ' '; ++i) {
1283  ;
1284  }
1285 
1286  if (buff[i] == '\n') {
1287  newline_count++;
1288  goto start;
1289  }
1290 
1291  buff[6] = ' ';
1292  bp = buff + 7;
1293 
1294  if (unlikely(continuation)) {
1295  /* Line continuation */
1296  need_continuation = 0;
1297  for (; *bp == ' '; ++bp) {
1298  ;
1299  }
1300  /* Validate concatenation */
1301  if (consecutive_quotation) {
1302  if (bp[0] == quotation_mark && bp[1] == quotation_mark) {
1303  bp++;
1304  } else {
1306  _("Invalid line continuation"));
1307  return YY_NULL;
1308  }
1309  quotation_mark = 0;
1311  } else if (quotation_mark) {
1312  /* Literal concatenation */
1313  if (*bp == quotation_mark) {
1314  bp++;
1315  } else {
1317  _("Invalid line continuation"));
1318  return YY_NULL;
1319  }
1320  }
1321  } else {
1322  /* Normal line */
1323  if (need_continuation) {
1325  _("Continuation character expected"));
1326  need_continuation = 0;
1327  }
1328  quotation_mark = 0;
1330  }
1331 
1332  /* Check if string literal is to be continued */
1333  for (i = bp - buff; buff[i] != '\n'; ++i) {
1334  /* Pick up floating comment and force loop exit */
1335  if (!quotation_mark && ((buff[i] == '*' && buff[i + 1] == '>') ||
1336  (cb_flag_acucomment && buff[i] == '|') ) ) {
1337  /* remove indicator "source text too long" if the column
1338  leading to the indicator comes after the floating comment
1339  */
1340  if (i < cb_text_column) {
1341  line_overflow = 0;
1342  }
1343  /* Set to null, 'i' is predecremented further below */
1344  buff[i] = 0;
1345  break;
1346  } else if (buff[i] == '\'' || buff[i] == '"') {
1347  if (quotation_mark == 0) {
1348  /* Literal start */
1349  quotation_mark = buff[i];
1350  } else if (quotation_mark == buff[i]) {
1351  if (i == cb_text_column - 1) {
1352  /* Consecutive quotation */
1354  } else {
1355  /* Literal end */
1356  quotation_mark = 0;
1357  }
1358  }
1359  }
1360  }
1361 
1362  if (unlikely(quotation_mark)) {
1363  /* Expecting continuation */
1364  if (!consecutive_quotation) {
1365  need_continuation = 1;
1366  }
1367  for (; i < cb_text_column;) {
1368  buff[i++] = ' ';
1369  }
1370  buff[i] = 0;
1371  } else {
1372  /* Truncate trailing spaces, including the newline */
1373  for (i--; i >= 0 && buff[i] == ' '; i--) {
1374  ;
1375  }
1376  if (i < 0) {
1377  /* Empty line after removing floating comment */
1378  newline_count++;
1379  goto start;
1380  }
1381  if (buff[i] == '\'' || buff[i] == '\"') {
1382  buff[++i] = ' ';
1383  }
1384  buff[i + 1] = 0;
1385  }
1386 
1387  /* Show warning if text is longer than cb_text_column
1388  and not whitespace (postponed here) */
1389  if (line_overflow != 0) {
1391  _("Source text after column %d"),
1392  cb_text_column);
1393  }
1394 
1395  if (unlikely(continuation)) {
1396  gotcr = strlen (bp);
1397  memmove (buff, bp, gotcr + 1);
1398  newline_count++;
1399  } else {
1400  /* Insert newlines at the start of the buffer */
1401  gotcr = strlen (buff);
1402  if (newline_count != 0) {
1403  memmove (buff + newline_count, buff, gotcr + 1);
1404  memset (buff, '\n', newline_count);
1405  gotcr += newline_count;
1406  }
1407  newline_count = 1;
1408  }
1409  return (int)gotcr;
1410 }
static void skip_to_eol ( void  )
static

References input(), and unput.

Referenced by check_comments().

1583 {
1584  int c;
1585 
1586  /* Skip bytes to end of line */
1587  while ((c = input ()) != EOF) {
1588  if (c == '\n') {
1589  break;
1590  }
1591  }
1592  if (c != EOF) {
1593  unput (c);
1594  }
1595 }
yy_switch_to_buffer ( buffer  )

Variable Documentation

option option case insensitive option never interactive option prefix

Referenced by cob_chk_file_env().