1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet * Copyright 2010-2014, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_reflect_utils.h"
183f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
193f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang#include <cstdio>
20b1980a2eedc56df92786afc291e00f26659a60adMike Lockwood#include <cstring>
21e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
22129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet#include <iomanip>
233f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
248c6d9b2d36ed2d6d811279fd9bddc05fffe16803Zonr Chang#include "llvm/ADT/StringRef.h"
253eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines#include "llvm/Support/FileSystem.h"
263eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines#include "llvm/Support/Path.h"
278c6d9b2d36ed2d6d811279fd9bddc05fffe16803Zonr Chang
288d5a2f6ab321615bfb3a46f68aff0b643a71caa0Raphael#include "os_sep.h"
2944d495d2ad8c350a8f586502c9ee8e97a513646aStephen Hines#include "slang_assert.h"
303f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
313f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wangnamespace slang {
323f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
333f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wangusing std::string;
343f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
352ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouilletstring RSSlangReflectUtils::GetFileNameStem(const char *fileName) {
362ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  const char *dot = fileName + strlen(fileName);
372ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  const char *slash = dot - 1;
382ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  while (slash >= fileName) {
392ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if (*slash == OS_PATH_SEPARATOR) {
402ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      break;
41dba3111408b307d8454830107ff61089ab7c5d6dYing Wang    }
422ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if ((*slash == '.') && (*dot == 0)) {
432ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      dot = slash;
442ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    }
452ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    --slash;
462ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
472ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  ++slash;
482ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return string(slash, dot - slash);
49dba3111408b307d8454830107ff61089ab7c5d6dYing Wang}
50dba3111408b307d8454830107ff61089ab7c5d6dYing Wang
512ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouilletstring RSSlangReflectUtils::ComputePackagedPath(const char *prefixPath,
522ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet                                                const char *packageName) {
532ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  string packaged_path(prefixPath);
542ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  if (!packaged_path.empty() &&
552ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      (packaged_path[packaged_path.length() - 1] != OS_PATH_SEPARATOR)) {
562ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    packaged_path += OS_PATH_SEPARATOR_STR;
572ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
582ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  size_t s = packaged_path.length();
592ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  packaged_path += packageName;
602ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  while (s < packaged_path.length()) {
612ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if (packaged_path[s] == '.') {
622ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      packaged_path[s] = OS_PATH_SEPARATOR;
633f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang    }
642ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    ++s;
652ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
662ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return packaged_path;
673f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang}
683f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
696315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrstatic string InternalFileNameConvert(const char *rsFileName, bool toLower) {
702ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  const char *dot = rsFileName + strlen(rsFileName);
712ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  const char *slash = dot - 1;
722ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  while (slash >= rsFileName) {
732ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if (*slash == OS_PATH_SEPARATOR) {
742ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      break;
752ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    }
762ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if ((*slash == '.') && (*dot == 0)) {
772ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      dot = slash;
783f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang    }
792ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    --slash;
802ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
812ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  ++slash;
822ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  char ret[256];
832ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  int i = 0;
842ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  for (; (i < 255) && (slash < dot); ++slash) {
852ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    if (isalnum(*slash) || *slash == '_') {
862ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      if (toLower) {
872ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet        ret[i] = tolower(*slash);
882ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      } else {
892ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet        ret[i] = *slash;
902ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      }
912ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      ++i;
923f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang    }
932ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
942ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  ret[i] = 0;
952ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return string(ret);
963f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang}
973f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
982ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouilletstd::string
992ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc BrouilletRSSlangReflectUtils::JavaClassNameFromRSFileName(const char *rsFileName) {
1002ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return InternalFileNameConvert(rsFileName, false);
1013f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang}
1023f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
103efcff1017f5f1e120a8ffb67125e412343479f94Jean-Luc Brouilletstd::string RootNameFromRSFileName(const std::string &rsFileName) {
104efcff1017f5f1e120a8ffb67125e412343479f94Jean-Luc Brouillet  return InternalFileNameConvert(rsFileName.c_str(), false);
105efcff1017f5f1e120a8ffb67125e412343479f94Jean-Luc Brouillet}
106efcff1017f5f1e120a8ffb67125e412343479f94Jean-Luc Brouillet
1072ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouilletstd::string
1082ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc BrouilletRSSlangReflectUtils::BCFileNameFromRSFileName(const char *rsFileName) {
1092ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return InternalFileNameConvert(rsFileName, true);
1103f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang}
1113f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
11244d495d2ad8c350a8f586502c9ee8e97a513646aStephen Hinesstd::string RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName(
11344d495d2ad8c350a8f586502c9ee8e97a513646aStephen Hines    const char *rsFileName) {
1142ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  std::string tmp(InternalFileNameConvert(rsFileName, false));
1152ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return tmp.append("BitCode");
11644d495d2ad8c350a8f586502c9ee8e97a513646aStephen Hines}
1170877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
118129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletstatic bool GenerateAccessorMethod(
119129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    const RSSlangReflectUtils::BitCodeAccessorContext &context,
1209ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    int bitwidth, GeneratedFile &out) {
1212ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // the prototype of the accessor method
1229ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "// return byte array representation of the " << bitwidth
1239ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines               << "-bit bitcode.\n";
1249ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "public static byte[] getBitCode" << bitwidth << "()";
125129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.startBlock();
1269ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "return getBitCode" << bitwidth << "Internal();\n";
127129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.endBlock(true);
1282ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return true;
1290877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang}
1300877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
1310877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang// Java method size must not exceed 64k,
1320877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang// so we have to split the bitcode into multiple segments.
1339ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hinesstatic bool GenerateSegmentMethod(const char *buff, int blen, int bitwidth,
1349ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                  int seg_num, GeneratedFile &out) {
1359ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "private static byte[] getSegment" << bitwidth << "_"
1369ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines               << seg_num << "()";
137129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.startBlock();
138129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "byte[] data = {";
139129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.increaseIndent();
140129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
141129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  const int kEntriesPerLine = 16;
142129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  int position = kEntriesPerLine;  // We start with a new line and indent.
143129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  for (int written = 0; written < blen; written++) {
144129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    if (++position >= kEntriesPerLine) {
145129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet      out << "\n";
146129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet      out.indent();
147129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet      position = 0;
148129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    } else {
149129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet      out << " ";
1500877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang    }
151129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    out << std::setw(4) << static_cast<int>(buff[written]) << ",";
1522ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
153129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << "\n";
1540877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
155129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.decreaseIndent();
156129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "};\n";
157129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "return data;\n";
158129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.endBlock();
1593f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang
1602ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return true;
1610877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang}
1620877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
1639ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hinesstatic bool GenerateJavaCodeAccessorMethodForBitwidth(
164129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    const RSSlangReflectUtils::BitCodeAccessorContext &context,
1659ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    int bitwidth, GeneratedFile &out) {
1669ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1679ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  std::string filename(context.bc32FileName);
1689ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (bitwidth == 64) {
1699ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    filename = context.bc64FileName;
1709ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
1719ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1729ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  FILE *pfin = fopen(filename.c_str(), "rb");
1735abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (pfin == nullptr) {
1749ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    fprintf(stderr, "Error: could not read file %s\n", filename.c_str());
1752ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    return false;
1762ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
1772ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
1782ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // start the accessor method
1799ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  GenerateAccessorMethod(context, bitwidth, out);
1802ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
1812ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // output the data
1822ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // make sure the generated function for a segment won't break the Javac
1832ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // size limitation (64K).
1842ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  static const int SEG_SIZE = 0x2000;
1852ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  char *buff = new char[SEG_SIZE];
1862ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  int read_length;
1872ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  int seg_num = 0;
1882ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  int total_length = 0;
1892ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  while ((read_length = fread(buff, 1, SEG_SIZE, pfin)) > 0) {
1909ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    GenerateSegmentMethod(buff, read_length, bitwidth, seg_num, out);
1912ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    ++seg_num;
1922ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    total_length += read_length;
1932ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
1942ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  delete[] buff;
1952ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  fclose(pfin);
1962ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
1972ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // output the internal accessor method
1989ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "private static int bitCode" << bitwidth << "Length = "
1999ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines               << total_length << ";\n\n";
2009ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "private static byte[] getBitCode" << bitwidth
2019ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines               << "Internal()";
202129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.startBlock();
2039ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  out.indent() << "byte[] bc = new byte[bitCode" << bitwidth << "Length];\n";
204129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "int offset = 0;\n";
205129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "byte[] seg;\n";
2062ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  for (int i = 0; i < seg_num; ++i) {
2079ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    out.indent() << "seg = getSegment" << bitwidth << "_" << i << "();\n";
208129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    out.indent() << "System.arraycopy(seg, 0, bc, offset, seg.length);\n";
209129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    out.indent() << "offset += seg.length;\n";
2102ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
211129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.indent() << "return bc;\n";
212129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.endBlock();
2130877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
2142ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return true;
2150877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang}
2160877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
2179ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hinesstatic bool GenerateJavaCodeAccessorMethod(
2189ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    const RSSlangReflectUtils::BitCodeAccessorContext &context,
2199ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    GeneratedFile &out) {
2209ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (!GenerateJavaCodeAccessorMethodForBitwidth(context, 32, out)) {
2219ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    slangAssert(false && "Couldn't generate 32-bit embedded bitcode!");
2229ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    return false;
2239ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
2249ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (!GenerateJavaCodeAccessorMethodForBitwidth(context, 64, out)) {
2259ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    slangAssert(false && "Couldn't generate 64-bit embedded bitcode!");
2269ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    return false;
2279ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
2289ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
2299ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  return true;
2309ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines}
2319ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
2320877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wangstatic bool GenerateAccessorClass(
2336315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    const RSSlangReflectUtils::BitCodeAccessorContext &context,
234129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    const char *clazz_name, GeneratedFile &out) {
2352ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // begin the class.
236129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << "/**\n";
237129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << " * @hide\n";
238129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << " */\n";
239129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << "public class " << clazz_name;
240129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.startBlock();
2412ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
2422ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  bool ret = true;
2432ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  switch (context.bcStorage) {
2442ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  case BCST_APK_RESOURCE:
2452ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    slangAssert(false &&
2462ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet                "Invalid generation of bitcode accessor with resource");
2472ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    break;
2482ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  case BCST_JAVA_CODE:
249129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    ret = GenerateJavaCodeAccessorMethod(context, out);
2502ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    break;
2512ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  default:
2522ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    ret = false;
2532ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
2542ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
2552ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  // end the class.
256129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.endBlock();
2572ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
2582ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return ret;
2590877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang}
2600877f0557e5c406fc8ff33c928a8ae969a5f4905Ying Wang
261129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletbool RSSlangReflectUtils::GenerateJavaBitCodeAccessor(
2626315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    const BitCodeAccessorContext &context) {
2632ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  string output_path =
2642ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet      ComputePackagedPath(context.reflectPath, context.packageName);
2653eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines  if (std::error_code EC = llvm::sys::fs::create_directories(
2663eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines          llvm::sys::path::parent_path(output_path))) {
2673eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines    fprintf(stderr, "Error: could not create dir %s: %s\n",
2683eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines            output_path.c_str(), EC.message().c_str());
2692ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    return false;
2702ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
2712ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
2722ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  string clazz_name(JavaBitcodeClassNameFromRSFileName(context.rsFileName));
2732ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  string filename(clazz_name);
2742ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  filename += ".java";
2752ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
276129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  GeneratedFile out;
277129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (!out.startFile(output_path, filename, context.rsFileName,
278fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines                     context.licenseNote, true, context.verbose)) {
2792ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet    return false;
2802ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  }
2812ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
282129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out << "package " << context.packageName << ";\n\n";
2832ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet
284129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  bool ret = GenerateAccessorClass(context, clazz_name.c_str(), out);
285129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
286129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  out.closeFile();
2872ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet  return ret;
2883f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang}
289129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
290129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletstd::string JoinPath(const std::string &path1, const std::string &path2) {
291129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (path1.empty()) {
292129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    return path2;
293129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
294129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (path2.empty()) {
295129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    return path1;
296129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
297129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  std::string fullPath = path1;
298129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (fullPath[fullPath.length() - 1] != OS_PATH_SEPARATOR) {
299129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    fullPath += OS_PATH_SEPARATOR;
300129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
301129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (path2[0] == OS_PATH_SEPARATOR) {
302129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    fullPath += path2.substr(1, string::npos);
303129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  } else {
304129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    fullPath += path2;
305129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
306129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  return fullPath;
307129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet}
308129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
309f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet// Replace all instances of "\" with "\\" in a single string to prevent
310f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet// formatting errors.  In Java, this can happen even within comments, as
311f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet// Java processes \u before the comments are stripped.  E.g. if the generated
312f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet// file in Windows contains the note:
313f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet//     /* Do not modify!  Generated from \Users\MyName\MyDir\foo.cs */
314f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet// Java will think that \U tells of a Unicode character.
315f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouilletstatic void SanitizeString(std::string *s) {
316f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  size_t p = 0;
317f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  while ((p = s->find('\\', p)) != std::string::npos) {
318f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet    s->replace(p, 1, "\\\\");
319f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet    p += 2;
320f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  }
321f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet}
322f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet
323129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletstatic const char *const gApacheLicenseNote =
324129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    "/*\n"
325129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * Copyright (C) 2011-2014 The Android Open Source Project\n"
326129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " *\n"
327129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
328129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * you may not use this file except in compliance with the License.\n"
329129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * You may obtain a copy of the License at\n"
330129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " *\n"
331129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
332129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " *\n"
333129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * Unless required by applicable law or agreed to in writing, software\n"
334129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
335129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
336129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    "implied.\n"
337129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * See the License for the specific language governing permissions and\n"
338129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " * limitations under the License.\n"
339129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    " */\n"
340129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    "\n";
341129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
342129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletbool GeneratedFile::startFile(const string &outDirectory,
343129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet                              const string &outFileName,
344129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet                              const string &sourceFileName,
345fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines                              const string *optionalLicense, bool isJava,
346fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines                              bool verbose) {
347fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines  if (verbose) {
348fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines    printf("Generating %s\n", outFileName.c_str());
349fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines  }
350129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
351129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  // Create the parent directories.
352129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (!outDirectory.empty()) {
3533eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines    if (std::error_code EC = llvm::sys::fs::create_directories(
3543eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines            llvm::sys::path::parent_path(outDirectory))) {
3553eb819ad8beec566a73b288204f9b75c2bb1d4e6Stephen Hines      fprintf(stderr, "Error: %s\n", EC.message().c_str());
356129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet      return false;
357129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    }
358129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
359129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
360129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  std::string FilePath = JoinPath(outDirectory, outFileName);
361129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
362129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  // Open the file.
363129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  open(FilePath.c_str());
364129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  if (!good()) {
365129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    fprintf(stderr, "Error: could not write file %s\n", outFileName.c_str());
366129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    return false;
367129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
368129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
369129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  // Write the license.
3705abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (optionalLicense != nullptr) {
371129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    *this << *optionalLicense;
372129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  } else {
373129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet    *this << gApacheLicenseNote;
374129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  }
375129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
376129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  // Write a notice that this is a generated file.
377f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  std::string source(sourceFileName);
378f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  if (isJava) {
379f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet    SanitizeString(&source);
380f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet  }
381f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet
382129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  *this << "/*\n"
383129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet        << " * This file is auto-generated. DO NOT MODIFY!\n"
384f33e1561dc390cf2be7a81e9f818b269d458ec7eJean-Luc Brouillet        << " * The source Renderscript file: " << source << "\n"
385129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet        << " */\n\n";
386129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
387129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  return true;
388129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet}
389129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
390129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletvoid GeneratedFile::closeFile() { close(); }
391129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
392129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletvoid GeneratedFile::increaseIndent() { mIndent.append("    "); }
393129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
394129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouilletvoid GeneratedFile::decreaseIndent() {
395129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  slangAssert(!mIndent.empty() && "No indent");
396129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet  mIndent.erase(0, 4);
397129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet}
398129fd8228cd04592a20c3d5009805a23585f2479Jean-Luc Brouillet
399c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouilletvoid GeneratedFile::comment(const std::string &s) {
400c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  indent() << "/* ";
401c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  // +3 for the " * " starting each line.
402c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  std::size_t indentLength = mIndent.length() + 3;
403c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  std::size_t lengthOfCommentOnLine = 0;
404c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  const std::size_t maxPerLine = 80;
405c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  for (std::size_t start = 0, length = s.length(), nextStart = 0;
406c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet       start < length; start = nextStart) {
407c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    std::size_t p = s.find_first_of(" \n", start);
408c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    std::size_t toCopy = 1;
409c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    bool forceBreak = false;
410c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    if (p == std::string::npos) {
411c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      toCopy = length - start;
412c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      nextStart = length;
413c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    } else {
414c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      toCopy = p - start;
415c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      nextStart = p + 1;
416c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      forceBreak = s[p] == '\n';
417c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    }
418c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    if (lengthOfCommentOnLine > 0) {
419c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      if (indentLength + lengthOfCommentOnLine + toCopy >= maxPerLine) {
420c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet        *this << "\n";
421c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet        indent() << " * ";
422c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet        lengthOfCommentOnLine = 0;
423c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      } else {
424c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet        *this << " ";
425c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      }
426c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    }
427c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet
428c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    *this << s.substr(start, toCopy);
429c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    if (forceBreak) {
430c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      lengthOfCommentOnLine = maxPerLine;
431c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    } else {
432c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet      lengthOfCommentOnLine += toCopy;
433c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet    }
434c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  }
435c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  *this << "\n";
436c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet  indent() << " */\n";
437c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet}
438c83b790079083da626cb64e37c38221bac1c8e8aJean-Luc Brouillet
4392ce118e843fcbd53488b503933136bb4fdbdfbc1Jean-Luc Brouillet} // namespace slang
440